个人中心的信息复杂度与产品本身有关。体系越庞大的产品,对应个人中心页面需要承载的内容越多,结构势必复杂。
一般平台型电商的个人中心页面必须涵盖:用户基础信息、全局性操作(设置)、关键数据记录、购买激励(会员、红包)、核心业务(订单信息)、工具集合(工具箱)等。
<template>
<view class="my-container">
<my-login v-if="!token"></my-login>
<my-userinfo v-else></my-userinfo>
</view>
</template>
<script>
import badgeMix from '@/mixins/tabbar-badge.js'
import { mapState } from 'vuex'
export default {
mixins: [badgeMix],
data() {
return {
};
},
computed: {
...mapState('m_user', ['token'])
}
}
</script>
<style lang="scss">
page,
.my-container {
height: 100%;
}
</style>
<template>
<view class="login-container">
<uni-icons type="contact-filled" size="100" color="#AFAFAF"></uni-icons>
<button type="primary" class="btn-login" open-type="getUserInfo" @getuserinfo="getUserInfo">一键登录</button>
<text class="tips-text">登录后尽享更多权益</text>
</view>
</template>
<script>
import { mapMutations, mapState } from 'vuex'
export default {
data() {
return {
};
},
computed: {
...mapState('m_user', ['redirectInfo'])
},
methods: {
...mapMutations('m_user', ['updateUserInfo', 'updateToken', 'updateRedirectInfo']),
// 用户授权之后,获取用户的基本信息
getUserInfo(e) {
console.log(e)
if (e.detail.errMsg === 'getUserInfo:fail auth deny') return uni.$showMsg('您取消了登录授权!')
console.log(e.detail.userInfo)
this.updateUserInfo(e.detail.userInfo)
this.getToken(e.detail)
},
async getToken(info) {
// 获取 code 对应的值
const [err, res] = await uni.login().catch(err => err)
if (err || res.errMsg !== 'login:ok') return uni.$showMsg('登录失败!')
// 准备参数
const query = {
code: res.code,
encryptedData: info.encryptedData,
iv: info.iv,
rawData: info.rawData,
signature: info.signature
}
const { data: loginResult } = await uni.$http.post('/api/public/v1/users/wxlogin', query)
if (loginResult.meta.status !== 200) return uni.$showMsg('登录失败!')
// 直接把 token 保存到 vuex 中
this.updateToken(loginResult.message.token)
this.navigateBack()
},
navigateBack() {
if (this.redirectInfo && this.redirectInfo.openType === 'switchTab') {
uni.switchTab({
url: this.redirectInfo.from,
complete: () => {
this.updateRedirectInfo(null)
}
})
}
}
}
}
</script>
<style lang="scss">
.login-container {
height: 750rpx;
background-color: #F8F8F8;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
overflow: hidden;
&::after {
content: ' ';
display: block;
width: 100%;
height: 40px;
background-color: white;
position: absolute;
bottom: 0;
left: 0;
border-radius: 100%;
transform: translateY(50%);
}
.btn-login {
width: 90%;
border-radius: 100px;
margin: 15px 0;
background-color: #C00000;
}
.tips-text {
font-size: 12px;
color: gray;
}
}
</style>
<template>
<view class="my-userinfo-container">
<!-- 头像和昵称区域 -->
<view class="top-box">
<image :src="userinfo.avatarUrl" class="avatar"></image>
<view class="nickname">{{userinfo.nickName}}</view>
</view>
<!-- 面板区域 -->
<view class="panel-list">
<!-- 第1个面板 -->
<view class="panel">
<view class="panel-body">
<view class="panel-item">
<text>8</text>
<text>收藏的店铺</text>
</view>
<view class="panel-item">
<text>14</text>
<text>收藏的商品</text>
</view>
<view class="panel-item">
<text>18</text>
<text>关注的商品</text>
</view>
<view class="panel-item">
<text>84</text>
<text>足迹</text>
</view>
</view>
</view>
<!-- 第2个面板 -->
<view class="panel">
<view class="panel-title">
我的订单
</view>
<view class="panel-body">
<view class="panel-item">
<image src="/static/my-icons/icon1.png" class="icon"></image>
<text>待付款</text>
</view>
<view class="panel-item">
<image src="/static/my-icons/icon2.png" class="icon"></image>
<text>待收货</text>
</view>
<view class="panel-item">
<image src="/static/my-icons/icon3.png" class="icon"></image>
<text>退款/退货</text>
</view>
<view class="panel-item">
<image src="/static/my-icons/icon4.png" class="icon"></image>
<text>全部订单</text>
</view>
</view>
</view>
<!-- 第3个面板 -->
<view class="panel">
<view class="panel-list-item">
<text>收货地址</text>
<uni-icons type="arrowright" size="15"></uni-icons>
</view>
<view class="panel-list-item">
<text>联系客服</text>
<uni-icons type="arrowright" size="15"></uni-icons>
</view>
<view class="panel-list-item" @click="logout">
<text>退出登录</text>
<uni-icons type="arrowright" size="15"></uni-icons>
</view>
</view>
</view>
</view>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
data() {
return {
};
},
computed: {
...mapState('m_user', ['userinfo'])
},
methods: {
...mapMutations('m_user', ['updateAddress', 'updateUserInfo', 'updateToken']),
async logout() {
const [err, succ] = await uni.showModal({
title: '提示',
content: '确认退出登录吗?'
}).catch(err => err)
if (succ && succ.confirm) {
this.updateAddress({})
this.updateUserInfo({})
this.updateToken('')
}
}
}
}
</script>
<style lang="scss">
.my-userinfo-container {
height: 100%;
background-color: #F4F4F4;
.top-box {
height: 400rpx;
background-color: #C00000;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
.avatar {
width: 90px;
height: 90px;
border-radius: 45px;
border: 2px solid #FFF;
box-shadow: 0 1px 5px black;
}
.nickname {
font-size: 16px;
color: #FFF;
font-weight: bold;
margin-top: 10px;
}
}
}
.panel-list {
padding: 0 10px;
position: relative;
top: -10px;
.panel {
background-color: white;
border-radius: 3px;
margin-bottom: 8px;
.panel-title {
line-height: 45px;
padding-left: 10px;
font-size: 15px;
border-bottom: 1px solid #F4F4F4;
}
.panel-body {
display: flex;
justify-content: space-around;
.panel-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
padding: 10px 0;
font-size: 13px;
.icon {
width: 35px;
height: 35px;
}
}
}
}
}
.panel-list-item {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 15px;
padding: 0 10px;
line-height: 45px;
}
</style>