You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
252 lines
5.8 KiB
252 lines
5.8 KiB
<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: config.LIB_CODE,
|
|
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>
|