Files
2026-02-08 09:30:43 +08:00

269 lines
6.7 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="page">
<view class="padding bg-white">
<!-- 头像 -->
<view class="flex justify-between align-center padding-tb solid-bottom" @click="chooseAvatar">
<view class="text-black">头像</view>
<view class="flex align-center">
<image class="avatar" :src="avatarPreview || getImageUrl(userInfo.avatar) || defaultAvatar" mode="aspectFill"></image>
<view class="lg text-gray cuIcon-right margin-left-xs"></view>
</view>
</view>
<!-- 昵称 -->
<view class="flex justify-between align-center padding-tb solid-bottom">
<view class="text-black label-text">昵称</view>
<view class="flex align-center flex-sub justify-end">
<input class="input-right" v-model="userInfo.nickName" placeholder="请输入昵称" />
<view class="lg text-gray cuIcon-right margin-left-xs"></view>
</view>
</view>
<!-- 电话号码 -->
<view class="flex justify-between align-center padding-tb solid-bottom">
<view class="text-black label-text">电话号码</view>
<view class="flex align-center flex-sub justify-end">
<input class="input-right" v-model="userInfo.phonenumber" placeholder="请输入电话号码" type="number" />
<view class="lg text-gray cuIcon-right margin-left-xs"></view>
</view>
</view>
<!-- 邮箱 -->
<view class="flex justify-between align-center padding-tb solid-bottom">
<view class="text-black label-text">邮箱</view>
<view class="flex align-center flex-sub justify-end">
<input class="input-right" v-model="userInfo.email" placeholder="请输入邮箱" />
<view class="lg text-gray cuIcon-right margin-left-xs"></view>
</view>
</view>
<!-- 性别 -->
<view class="flex justify-between align-center padding-tb solid-bottom">
<view class="text-black">性别</view>
<view class="flex align-center">
<view class="gender-switch">
<view
class="gender-item"
:class="{ 'gender-active': userInfo.sex === '0', 'gender-male': userInfo.sex === '0' }"
@click="userInfo.sex = '0'"
>
<text class="cuIcon-male"></text>
</view>
<view
class="gender-item"
:class="{ 'gender-active': userInfo.sex === '1', 'gender-female': userInfo.sex === '1' }"
@click="userInfo.sex = '1'"
>
<text class="cuIcon-female"></text>
</view>
</view>
</view>
</view>
<button class="bg-blue round margin-top-xl" @click="handleSave" :loading="saving">保存</button>
</view>
</view>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { baseUrl, getToken } from '@/request/request.js';
import { getProfileDetail, updateProfile } from '@/request/three_one_api/info.js';
const saving = ref(false);
const defaultAvatar = 'https://ossweb-img.qq.com/images/lol/web201310/skin/big81005.jpg';
const avatarPreview = ref(''); // 用于显示选择的图片临时预览
const userInfo = reactive({
avatar: '', // 保存相对路径,用于提交
nickName: '',
phonenumber: '',
email: '',
sex: '0' // '0'-男 '1'-女
});
// 获取图片完整URL用于显示
const getImageUrl = (path) => {
if (!path) return '';
if (path.startsWith('http')) return path;
return baseUrl + path;
};
// 页面加载时获取个人信息
onMounted(() => {
loadProfileDetail();
});
// 获取个人信息
const loadProfileDetail = async () => {
try {
uni.showLoading({ title: '加载中...' });
const res = await getProfileDetail();
uni.hideLoading();
if (res.code === 0 && res.data) {
userInfo.avatar = res.data.avatar || '';
userInfo.nickName = res.data.nickName || '';
userInfo.phonenumber = res.data.phonenumber || '';
userInfo.email = res.data.email || '';
userInfo.sex = res.data.sex || '0';
}
} catch (err) {
uni.hideLoading();
console.error('获取个人信息失败:', err);
}
};
// 选择头像
const chooseAvatar = () => {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
const tempFilePath = res.tempFilePaths[0];
// 显示临时预览
avatarPreview.value = tempFilePath;
// 上传获取链接
uploadAvatar(tempFilePath);
}
});
};
// 上传头像获取链接
const uploadAvatar = (filePath) => {
uni.showLoading({ title: '上传中...' });
uni.uploadFile({
url: baseUrl + '/frontend/attachment/upload',
filePath: filePath,
name: 'file',
header: {
'Authorization': getToken()
},
success: (uploadRes) => {
uni.hideLoading();
try {
const data = JSON.parse(uploadRes.data);
if (data.code === 0 && data.data) {
// 上传成功,保存相对路径(用于提交)
userInfo.avatar = data.data.url || data.data;
uni.showToast({ title: '上传成功', icon: 'success' });
} else {
avatarPreview.value = ''; // 上传失败,清除预览
uni.showToast({ title: data.msg || '上传失败', icon: 'none' });
}
} catch (e) {
avatarPreview.value = '';
uni.showToast({ title: '上传失败', icon: 'none' });
}
},
fail: () => {
uni.hideLoading();
avatarPreview.value = '';
uni.showToast({ title: '上传失败', icon: 'none' });
}
});
};
// 保存
const handleSave = async () => {
// 表单验证
if (!userInfo.nickName) {
uni.showToast({ title: '请输入昵称', icon: 'none' });
return;
}
saving.value = true;
try {
const params = {
nickName: userInfo.nickName,
phonenumber: userInfo.phonenumber,
email: userInfo.email,
sex: userInfo.sex,
avatar: userInfo.avatar // 提交相对路径
};
const res = await updateProfile(params);
if (res.code === 0) {
uni.showToast({ title: '保存成功', icon: 'success' });
setTimeout(() => {
uni.navigateBack();
}, 1500);
} else {
uni.showToast({ title: res.msg || '保存失败', icon: 'none' });
}
} catch (err) {
console.error('保存失败:', err);
uni.showToast({ title: '保存失败', icon: 'none' });
} finally {
saving.value = false;
}
};
</script>
<style lang="scss" scoped>
.page {
min-height: 100vh;
background: #f5f5f5;
}
.avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
}
.label-text {
flex-shrink: 0;
margin-right: 20rpx;
}
.input-right {
text-align: right;
font-size: 28rpx;
color: #333;
}
.padding-tb {
padding: 30rpx 0;
}
.gender-switch {
display: flex;
align-items: center;
background: #f0f0f0;
border-radius: 40rpx;
padding: 4rpx;
}
.gender-item {
width: 60rpx;
height: 60rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
color: #999;
transition: all 0.3s;
}
.gender-active {
color: #fff;
}
.gender-male {
background: #2667E9;
}
.gender-female {
background: #ff6b81;
}
.line-blue {
border: 1rpx solid #2667E9;
color: #2667E9;
background: #fff;
}
</style>