<template>
|
<view class="page">
|
<!-- 自定义导航栏:状态栏留白由行内 paddingTop 撑开 -->
|
<view class="nav" :style="{ paddingTop: statusBarHeight + 'px' }">
|
<view class="nav-bar">
|
<!-- 返回 -->
|
<view class="nav-back" @tap="handleBack">
|
<view class="icon-back"></view>
|
</view>
|
<text class="nav-title">我的资料</text>
|
<!-- 更多 / 帮助(本期占位) -->
|
<view class="nav-actions">
|
<view class="nav-action" @tap="handlePlaceholder('更多')">
|
<view class="icon-more">
|
<view class="dot"></view>
|
<view class="dot"></view>
|
<view class="dot"></view>
|
</view>
|
</view>
|
<view class="nav-action" @tap="handlePlaceholder('帮助')">
|
<view class="icon-help"><text class="icon-help-text">?</text></view>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<view class="body">
|
<view class="list">
|
<!-- 头像:点击更换(本期占位) -->
|
<view class="row" @tap="handlePlaceholder('头像更换')">
|
<text class="row-label">头像</text>
|
<view class="row-right">
|
<view class="avatar">
|
<image v-if="avatar" class="avatar-img" :src="avatar" mode="aspectFill" />
|
<view v-else class="icon icon-camera"></view>
|
</view>
|
<view class="icon icon-chevron-right"></view>
|
</view>
|
</view>
|
|
<!-- 手机号:小程序内暂不支持更换,仅只读展示(已脱敏),故无箭头 -->
|
<view class="row">
|
<text class="row-label">手机号</text>
|
<text class="row-value">{{ phone || '—' }}</text>
|
</view>
|
|
<!-- 实名认证 -->
|
<view class="row" @tap="handlePlaceholder('实名认证')">
|
<text class="row-label">实名认证</text>
|
<view class="row-right">
|
<view class="badge" :class="realNameBadge.cls">
|
<text class="badge-text">{{ realNameBadge.text }}</text>
|
</view>
|
<view class="icon icon-chevron-right"></view>
|
</view>
|
</view>
|
|
<!-- 企业 / 个体户认证 -->
|
<view class="row" @tap="handlePlaceholder('企业/个体户认证')">
|
<text class="row-label">企业/个体户认证</text>
|
<view class="row-right">
|
<view class="badge" :class="companyBadge.cls">
|
<text class="badge-text">{{ companyBadge.text }}</text>
|
</view>
|
<view class="icon icon-chevron-right"></view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 底部操作区 -->
|
<view class="footer">
|
<view class="btn-logout" @tap="handleLogout">
|
<text class="btn-logout-text">退出登录</text>
|
</view>
|
<text class="link-cancel" @tap="handlePlaceholder('注销账号')">注销账号</text>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<script setup>
|
import { computed, ref } from 'vue'
|
import { onShow } from '@dcloudio/uni-app'
|
import { clearToken, ensureLogin } from '@/utils/request.js'
|
import { getMemberInfo, logout } from '@/api/index.js'
|
|
/** 状态栏高度:自定义导航栏下用于顶部留白 */
|
const statusBarHeight = uni.getSystemInfoSync().statusBarHeight || 0
|
|
/** 用户头像:登录后由 getMemberInfo 下发,为空时回退相机占位 */
|
const avatar = ref('')
|
|
/** 用户手机号:登录后由 getMemberInfo 下发(已脱敏,形如 133****5555) */
|
const phone = ref('')
|
|
/**
|
* 认证状态字典:key 为后端下发的状态枚举,值含徽标文案与样式类
|
* 本期为原型,两处认证均取 none(未认证)占位,后端接入后直接替换 ref 初值即可
|
*/
|
const AUTH_STATUS_MAP = {
|
none: { text: '未认证', cls: 'badge--none' },
|
ing: { text: '认证中', cls: 'badge--ing' },
|
fail: { text: '认证失败', cls: 'badge--fail' },
|
done: { text: '已认证', cls: 'badge--done' }
|
}
|
|
/** 实名认证状态(本期占位) */
|
const realNameStatus = ref('none')
|
|
/** 企业 / 个体户认证状态(本期占位) */
|
const companyStatus = ref('none')
|
|
/** 实名认证徽标:状态缺省兜底「未认证」 */
|
const realNameBadge = computed(() => AUTH_STATUS_MAP[realNameStatus.value] || AUTH_STATUS_MAP.none)
|
|
/** 企业 / 个体户认证徽标:状态缺省兜底「未认证」 */
|
const companyBadge = computed(() => AUTH_STATUS_MAP[companyStatus.value] || AUTH_STATUS_MAP.none)
|
|
/** 返回上一页:无上级页面(如直接进入)时回到个人中心 */
|
const handleBack = () => {
|
const pages = getCurrentPages()
|
if (pages.length > 1) {
|
uni.navigateBack()
|
return
|
}
|
uni.switchTab({ url: '/pages/profile/index' })
|
}
|
|
/** 占位交互:头像更换 / 实名认证 / 企业认证 / 注销 / 更多 / 帮助本期均不接后端 */
|
const handlePlaceholder = (name) => {
|
uni.showToast({ title: `${name}功能开发中`, icon: 'none' })
|
}
|
|
/** 退出登录:二次确认后调用退出接口并清理本地登录态,回到个人中心 */
|
const handleLogout = () => {
|
uni.showModal({
|
title: '提示',
|
content: '确定要退出登录吗?',
|
confirmText: '退出',
|
cancelText: '取消',
|
success: async (res) => {
|
if (!res.confirm) return
|
try {
|
await logout()
|
} catch (error) {
|
// 退出接口失败不阻塞本地退出,仅记录上下文日志
|
console.error('[PROFILE_EDIT] 退出登录接口失败', error)
|
}
|
clearToken()
|
uni.reLaunch({ url: '/pages/profile/index' })
|
}
|
})
|
}
|
|
/** 拉取当前会员信息(头像 / 脱敏手机号),失败时静默降级为空 */
|
const loadMemberInfo = async () => {
|
try {
|
const res = await getMemberInfo()
|
const data = res.data || {}
|
avatar.value = data.avatar || ''
|
phone.value = data.phone || ''
|
} catch (error) {
|
console.error('[PROFILE_EDIT] 拉取会员信息失败', error)
|
avatar.value = ''
|
phone.value = ''
|
}
|
}
|
|
// 进入页面校验登录态,未登录跳登录页;已登录则拉取会员信息
|
onShow(() => {
|
if (!ensureLogin()) return
|
loadMemberInfo()
|
})
|
</script>
|
|
<style scoped lang="scss">
|
.page {
|
min-height: 100vh;
|
display: flex;
|
flex-direction: column;
|
box-sizing: border-box;
|
background-color: #ffffff;
|
}
|
|
/* ==================== 自定义导航栏 ==================== */
|
|
.nav {
|
flex-shrink: 0;
|
background-color: #ffffff;
|
}
|
|
.nav-bar {
|
position: relative;
|
height: 88rpx;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.nav-back {
|
position: absolute;
|
left: 16rpx;
|
top: 50%;
|
transform: translateY(-50%);
|
width: 64rpx;
|
height: 64rpx;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
/* 纯 CSS 左向箭头:左 + 下边框旋转 45° */
|
.icon-back {
|
width: 22rpx;
|
height: 22rpx;
|
border-left: 4rpx solid #1f2937;
|
border-bottom: 4rpx solid #1f2937;
|
transform: rotate(45deg);
|
}
|
|
.nav-title {
|
font-size: 34rpx;
|
font-weight: 700;
|
line-height: 1;
|
letter-spacing: 1rpx;
|
color: #0f172a;
|
}
|
|
.nav-actions {
|
position: absolute;
|
right: 28rpx;
|
top: 50%;
|
transform: translateY(-50%);
|
display: flex;
|
align-items: center;
|
gap: 32rpx;
|
}
|
|
.nav-action {
|
width: 56rpx;
|
height: 56rpx;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
/* 更多:三点 */
|
.icon-more {
|
display: flex;
|
align-items: center;
|
gap: 6rpx;
|
}
|
|
.icon-more .dot {
|
width: 8rpx;
|
height: 8rpx;
|
border-radius: 50%;
|
background: #334155;
|
}
|
|
/* 帮助:圆圈问号 */
|
.icon-help {
|
width: 36rpx;
|
height: 36rpx;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
box-sizing: border-box;
|
border: 3rpx solid #334155;
|
border-radius: 50%;
|
}
|
|
.icon-help-text {
|
font-size: 22rpx;
|
font-weight: 700;
|
line-height: 1;
|
color: #334155;
|
}
|
|
/* ==================== 资料列表 ==================== */
|
|
.body {
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
}
|
|
.list {
|
padding: 8rpx 32rpx 0;
|
}
|
|
.row {
|
min-height: 116rpx;
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
border-bottom: 2rpx solid #f1f5f9;
|
}
|
|
/* 末行无分隔线 */
|
.row:last-child {
|
border-bottom: none;
|
}
|
|
.row-label {
|
font-size: 30rpx;
|
line-height: 1;
|
color: #1f2937;
|
}
|
|
.row-right {
|
display: flex;
|
align-items: center;
|
gap: 16rpx;
|
}
|
|
.row-value {
|
font-size: 30rpx;
|
line-height: 1;
|
letter-spacing: 1rpx;
|
color: #94a3b8;
|
}
|
|
/* 头像容器:46pt 圆形 */
|
.avatar {
|
width: 92rpx;
|
height: 92rpx;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
box-sizing: border-box;
|
border-radius: 50%;
|
background: #f1f5f9;
|
border: 2rpx solid #e2e8f0;
|
overflow: hidden;
|
}
|
|
.avatar-img {
|
width: 100%;
|
height: 100%;
|
border-radius: 50%;
|
}
|
|
/* ==================== 认证状态徽标(4 态) ==================== */
|
|
.badge {
|
display: flex;
|
align-items: center;
|
padding: 10rpx 20rpx;
|
border-radius: 12rpx;
|
border: 2rpx solid;
|
}
|
|
.badge-text {
|
font-size: 26rpx;
|
font-weight: 500;
|
line-height: 1;
|
}
|
|
/* 未认证 */
|
.badge--none {
|
color: #ea580c;
|
background: #fff7ed;
|
border-color: #fdba74;
|
}
|
|
/* 认证中 */
|
.badge--ing {
|
color: #1e5ebc;
|
background: #eff6ff;
|
border-color: #93c5fd;
|
}
|
|
/* 认证失败 */
|
.badge--fail {
|
color: #dc2626;
|
background: #fef2f2;
|
border-color: #fca5a5;
|
}
|
|
/* 已认证 */
|
.badge--done {
|
color: #4d7c0f;
|
background: #f7fee7;
|
border-color: #bef264;
|
}
|
|
/* ==================== 底部操作区 ==================== */
|
|
.footer {
|
/* 内容不足一屏时按钮自动贴底 */
|
margin-top: auto;
|
padding: 32rpx 48rpx 44rpx;
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
gap: 36rpx;
|
}
|
|
.btn-logout {
|
width: 100%;
|
height: 96rpx;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
border-radius: 48rpx;
|
background: linear-gradient(90deg, #82c236 0%, #639c1f 100%);
|
box-shadow: 0 16rpx 40rpx rgba(99, 156, 31, 0.28);
|
}
|
|
.btn-logout-text {
|
font-size: 30rpx;
|
font-weight: 600;
|
line-height: 1;
|
color: #ffffff;
|
}
|
|
.link-cancel {
|
font-size: 28rpx;
|
line-height: 1;
|
color: #1e5ebc;
|
text-decoration: underline;
|
}
|
|
/* ==================== 图标(内联 base64 SVG) ==================== */
|
|
.icon {
|
flex-shrink: 0;
|
background-repeat: no-repeat;
|
background-position: center center;
|
background-size: 100% 100%;
|
}
|
|
/* 相机占位(#94A3B8) */
|
.icon-camera {
|
width: 40rpx;
|
height: 40rpx;
|
background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTRBM0I4IiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTE0LjUgNGgtNUw3IDdINGEyIDIgMCAwIDAtMiAydjlhMiAyIDAgMCAwIDIgMmgxNmEyIDIgMCAwIDAgMi0yVjlhMiAyIDAgMCAwLTItMmgtM2wtMi41LTN6Ii8+PGNpcmNsZSBjeD0iMTIiIGN5PSIxMyIgcj0iMyIvPjwvc3ZnPg==');
|
}
|
|
/* 右箭头(#94A3B8) */
|
.icon-chevron-right {
|
width: 32rpx;
|
height: 32rpx;
|
background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTRBM0I4IiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0ibTkgMTggNi02LTYtNiIvPjwvc3ZnPg==');
|
}
|
</style>
|