| | |
| | | |
| | | <view class="body"> |
| | | <view class="list"> |
| | | <!-- 头像:点击更换(本期占位) --> |
| | | <view class="row" @tap="handlePlaceholder('头像更换')"> |
| | | <!-- 头像:点击更换 --> |
| | | <view class="row" @tap="handleAvatarChange"> |
| | | <text class="row-label">头像</text> |
| | | <view class="row-right"> |
| | | <view class="avatar"> |
| | |
| | | </view> |
| | | |
| | | <!-- 实名认证 --> |
| | | <view class="row" @tap="handlePlaceholder('实名认证')"> |
| | | <view class="row" @tap="handleRealNameCertification"> |
| | | <text class="row-label">实名认证</text> |
| | | <view class="row-right"> |
| | | <view class="badge" :class="realNameBadge.cls"> |
| | |
| | | </view> |
| | | |
| | | <!-- 企业 / 个体户认证 --> |
| | | <view class="row" @tap="handlePlaceholder('企业/个体户认证')"> |
| | | <view class="row" @tap="handleCompanyCertification"> |
| | | <text class="row-label">企业/个体户认证</text> |
| | | <view class="row-right"> |
| | | <view class="badge" :class="companyBadge.cls"> |
| | |
| | | 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' |
| | | import { getMemberInfo, logout, uploadAvatarFile, updateAvatar } from '@/api/index.js' |
| | | |
| | | /** 状态栏高度:自定义导航栏下用于顶部留白 */ |
| | | const statusBarHeight = uni.getSystemInfoSync().statusBarHeight || 0 |
| | | |
| | | /** 头像文件大小上限:5MB(选图后前置校验,超限直接拒绝,避免无效上传) */ |
| | | const AVATAR_MAX_SIZE = 5 * 1024 * 1024 |
| | | |
| | | /** 用户头像:登录后由 getMemberInfo 下发,为空时回退相机占位 */ |
| | | const avatar = ref('') |
| | |
| | | const phone = ref('') |
| | | |
| | | /** |
| | | * 认证状态字典:key 为后端下发的状态枚举,值含徽标文案与样式类 |
| | | * 本期为原型,两处认证均取 none(未认证)占位,后端接入后直接替换 ref 初值即可 |
| | | * 认证状态字典:key 为本地徽标状态,值含徽标文案与样式类 |
| | | */ |
| | | const AUTH_STATUS_MAP = { |
| | | none: { text: '未认证', cls: 'badge--none' }, |
| | |
| | | done: { text: '已认证', cls: 'badge--done' } |
| | | } |
| | | |
| | | /** 实名认证状态(本期占位) */ |
| | | /** |
| | | * 后端认证状态码 → 本地徽标状态(0未认证 1审核中 2已认证 3认证失败) |
| | | * 个人中心「实名认证」行据此回显真实状态 |
| | | */ |
| | | const AUTH_STATUS_CODE_MAP = { |
| | | '0': 'none', |
| | | '1': 'ing', |
| | | '2': 'done', |
| | | '3': 'fail' |
| | | } |
| | | |
| | | /** 实名认证状态:由会员信息接口下发的 authStatus 映射,缺省「未认证」 */ |
| | | const realNameStatus = ref('none') |
| | | |
| | | /** 企业 / 个体户认证状态(本期占位) */ |
| | | /** 企业 / 个体户认证状态:由会员信息接口下发的 companyAuthStatus 映射,缺省「未认证」 */ |
| | | const companyStatus = ref('none') |
| | | |
| | | /** 实名认证徽标:状态缺省兜底「未认证」 */ |
| | |
| | | uni.switchTab({ url: '/pages/profile/index' }) |
| | | } |
| | | |
| | | /** 占位交互:头像更换 / 实名认证 / 企业认证 / 注销 / 更多 / 帮助本期均不接后端 */ |
| | | /** 占位交互:注销 / 更多 / 帮助本期均不接后端 */ |
| | | const handlePlaceholder = (name) => { |
| | | uni.showToast({ title: `${name}功能开发中`, icon: 'none' }) |
| | | } |
| | | |
| | | /** 跳转实名认证页(个人主体) */ |
| | | const handleRealNameCertification = () => { |
| | | uni.navigateTo({ url: '/pages/profile/certification' }) |
| | | } |
| | | |
| | | /** 跳转企业/个体认证向导页(企业 / 个体工商户主体) */ |
| | | const handleCompanyCertification = () => { |
| | | uni.navigateTo({ url: '/pages/profile/company-certification' }) |
| | | } |
| | | |
| | | /** |
| | | * 更换头像入口:先弹出选择方式(相册 / 拍照 / 取消) |
| | | * 说明:取消按钮由系统 ActionSheet 自带,用户取消时不触发 success,无需额外处理 |
| | | */ |
| | | const handleAvatarChange = () => { |
| | | uni.showActionSheet({ |
| | | itemList: ['从相册选择', '拍照上传'], |
| | | success: (res) => { |
| | | // tapIndex 0=相册 1=拍照 |
| | | chooseAndUploadAvatar(res.tapIndex === 1 ? 'camera' : 'album') |
| | | } |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * 选图并上传:选图 -> 大小校验 -> 上传文件服务 -> 写回会员资料 -> 本地即时回显 |
| | | * @param {String} sourceType 图片来源:'album' 相册 / 'camera' 拍照 |
| | | */ |
| | | const chooseAndUploadAvatar = (sourceType) => { |
| | | uni.chooseImage({ |
| | | count: 1, |
| | | sizeType: ['compressed'], |
| | | sourceType: [sourceType], |
| | | success: async (res) => { |
| | | const filePath = (res.tempFilePaths || [])[0] |
| | | const file = (res.tempFiles || [])[0] |
| | | if (!filePath) return |
| | | // 前置大小校验:超限直接提示,避免无效上传 |
| | | if (file && file.size > AVATAR_MAX_SIZE) { |
| | | uni.showToast({ title: '图片不能超过5MB', icon: 'none' }) |
| | | return |
| | | } |
| | | try { |
| | | // STEP 1: 上传文件到文件服务,拿到可访问 url |
| | | const uploadRes = await uploadAvatarFile(filePath) |
| | | const url = uploadRes.data && uploadRes.data.url |
| | | if (!url) { |
| | | uni.showToast({ title: '上传失败,请重试', icon: 'none' }) |
| | | return |
| | | } |
| | | // STEP 2: 把 url 写回会员资料 |
| | | await updateAvatar(url) |
| | | // STEP 3: 本地即时回显,无需再拉接口 |
| | | avatar.value = url |
| | | uni.showToast({ title: '头像已更新', icon: 'success' }) |
| | | } catch (error) { |
| | | console.error('[PROFILE_EDIT] 更新头像失败', error) |
| | | uni.showToast({ title: (error && error.message) || '更新头像失败', icon: 'none' }) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | /** 退出登录:二次确认后调用退出接口并清理本地登录态,回到个人中心 */ |
| | |
| | | }) |
| | | } |
| | | |
| | | /** 拉取当前会员信息(头像 / 脱敏手机号),失败时静默降级为空 */ |
| | | /** 拉取当前会员信息(头像 / 脱敏手机号 / 实名认证状态),失败时静默降级为空 */ |
| | | const loadMemberInfo = async () => { |
| | | try { |
| | | const res = await getMemberInfo() |
| | | const data = res.data || {} |
| | | avatar.value = data.avatar || '' |
| | | phone.value = data.phone || '' |
| | | // 实名认证徽标据后端 authStatus 映射回显(审核通过/驳回后再次进入本页即刷新) |
| | | realNameStatus.value = AUTH_STATUS_CODE_MAP[data.authStatus] || 'none' |
| | | // 企业/个体户认证徽标据后端 companyAuthStatus 映射回显,与实名认证相互独立 |
| | | companyStatus.value = AUTH_STATUS_CODE_MAP[data.companyAuthStatus] || 'none' |
| | | } catch (error) { |
| | | console.error('[PROFILE_EDIT] 拉取会员信息失败', error) |
| | | avatar.value = '' |
| | | phone.value = '' |
| | | realNameStatus.value = 'none' |
| | | companyStatus.value = 'none' |
| | | } |
| | | } |
| | | |