|
|
<template> <view class="user-info-page">
<view class="user-info-section"> <!-- 点击获取头像 --> <button open-type="chooseAvatar" @chooseavatar="onChooseAvatar" class="avatar-btn"> <image v-if="avatarUrl" :src="avatarUrl" class="avatar-img"></image> <image v-else src="@/static/images/logo.jpg" class="avatar-img"></image> <text class="tip-text">点击更换头像</text> </button> </view>
<!-- 昵称 --> <view class="form-item"> <text class="label">昵称</text> <input class="input" type="nickname" v-model="nickname" placeholder="请输入昵称" /> <uni-icons type="right" size="18" color="#ccc"></uni-icons> </view>
<!-- 保存按钮 --> <view class="save-box"> <button class="save-btn" @click="saveUserInfo">保存修改</button> </view> </view></template>
<script>import config from '@/utils/config'import { FetchBindRead } from '@/api/user';
const USER_KEY = 'user-info';
export default { data() { return { nickname: '', avatarUrl: '', // 仅存放 base64,用于显示
imgId: '', // 仅用于提交后端
saving: false // 防重复提交
}; }, onLoad() { this.loadUserInfo(); }, methods:{ // 加载用户信息
async loadUserInfo() { const userInfo = uni.getStorageSync(USER_KEY) || {}; this.nickname = userInfo.nickname || ''; const avatarId = userInfo.avatarId || ''; this.imgId = avatarId;
if (avatarId) { try { uni.showLoading({ title: '加载头像中...' }); const url = `${config.baseUrl}/api/fileRelevant/getImg?imgType=5&imgId=${avatarId}`; this.avatarUrl = await this.urlToBase64(url); } catch (err) { console.error('头像加载失败', err); this.avatarUrl = ''; } finally { uni.hideLoading(); } } else { this.avatarUrl = ''; } },
// 选择头像 + 上传 + 转base64预览
async onChooseAvatar(e) { const tempFilePath = e.detail.avatarUrl; uni.showLoading({ title: '上传中...' });
try { // 上传头像
const uploadRes = await new Promise((resolve, reject) => { uni.uploadFile({ url: config.baseUrl + '/api/fileRelevant/uploadWxAvatarImg', filePath: tempFilePath, name: 'file', success: resolve, fail: reject }); });
const resData = JSON.parse(uploadRes.data); const imgId = resData.data; this.imgId = imgId;
// 转base64显示
const url = `${config.baseUrl}/api/fileRelevant/getImg?imgType=5&imgId=${imgId}`; this.avatarUrl = await this.urlToBase64(url);
uni.showToast({ title: '头像上传成功', icon: 'success' }); } catch (err) { console.error(err); uni.showToast({ title: '头像上传失败', icon: 'none' }); } finally { uni.hideLoading(); } },
// 最简稳定版:图片链接转base64
urlToBase64(url) { return new Promise((resolve, reject) => { uni.request({ url, method: 'GET', responseType: 'arraybuffer', success: (res) => { try { const base64 = uni.arrayBufferToBase64(res.data); resolve(`data:image/jpeg;base64,${base64}`); } catch (e) { reject(e); } }, fail: reject }); }); },
// 保存(防重复提交 + 同步缓存)
async saveUserInfo() { if (this.saving) return; if (!this.nickname.trim()) { uni.showToast({ title: '请输入昵称', icon: 'none' }); return; }
this.saving = true; uni.showLoading({ title: '保存中...' });
try { const openId = uni.getStorageSync('wx_login_code') || ''; const params = { avatar: this.imgId, libcode: "1201", nickname: this.nickname, openid: openId };
await FetchBindRead(params);
// 保存到缓存
uni.setStorageSync(USER_KEY, { nickname: this.nickname, avatarId: this.imgId });
uni.showToast({ title: '保存成功', icon: 'success' }); setTimeout(() => { uni.navigateBack(); }, 1500);
} catch (error) { console.error(error); uni.showToast({ title: '保存失败', icon: 'none' }); } finally { uni.hideLoading(); this.saving = false; } } }};</script>
<style lang="scss" scoped>.user-info-page { background-color: #f5f5f5; min-height: 100vh; padding: 20rpx; box-sizing: border-box;}
.user-info-section { background: #fff; padding: 40rpx 0; border-radius: 12rpx; margin-bottom: 20rpx; display: flex; flex-direction: column; align-items: center;}
.avatar-btn { background: transparent; display: flex; flex-direction: column; align-items: center; &::after { border: none; }}
.avatar-img { width: 120rpx; height: 120rpx; border-radius: 50%; object-fit: cover; margin-bottom: 10rpx;}
.tip-text { font-size: 26rpx; color: #999;}
.form-item { background-color: #fff; display: flex; justify-content: space-between; align-items: center; padding: 0 30rpx; height: 88rpx; border-radius: 12rpx; margin-bottom: 20rpx;}
.label { font-size: 30rpx; color: #333; width: 120rpx;}
.input { flex: 1; font-size: 30rpx; color: #333; text-align: right;}
.save-box { margin-top: 60rpx; padding: 0 20rpx;}
.save-btn { height: 88rpx; line-height: 88rpx; background-color: #007aff; color: #fff; border-radius: 44rpx; font-size: 32rpx;}</style>
|