Files
wagoo-douy3/src/pages/client/mine/userInfo.vue
2026-04-10 13:17:20 +08:00

343 lines
8.0 KiB
Vue
Raw 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="mine-user-edit">
<view class="edit-content">
<view class="flex-row-between edit-cell">
<text class="title">头像</text>
<button class="flex-row-end user-avator" @click="chooseavatar">
<image class="avator-icon" :src="userInfo.head_pic_url" />
<!-- <image class="arrow-icon" :src="`${imgPrefix}right-arrow.png`" /> -->
</button>
</view>
<view class="flex-row-between edit-cell">
<text class="title">昵称</text>
<input class="fs-24 app-fc-main SourceHanSansCN-Medium edit-input" type="nickname"
placeholder-class="fs-24 app-fc-normal SourceHanSansCN-Regular app-text-right"
:value="userInfo.nick_name" placeholder="点击输入昵称" @change="
(e) =>
onChange(e.detail.value && e.detail.value.trim(), 'nick_name')
" />
</view>
<form-cell title="出生年月" type="checkDate" placeholderText="选择出生日期" :value="userInfo.birthday"
:defaultDate="userInfo.birthday" @onChange="(value) => onChange(value, 'birthday')" />
<form-cell title="性别" type="custom" :showRightArrow="false" :noBorder="true">
<view class="flex-row-end edit-sex" slot="right">
<view class="flex-center fs-24 app-fc-main SourceHanSansCN-Medium sex-item"
:class="[userInfo.sex === 1 ? 'active man' : '']" @click="onChange(1, 'sex')">
<image class="sex-item-img"
:src="userInfo.sex === 1 ? `${imgPrefix}whiteMale.png` : `${imgPrefix}record-maleImg.png`">
</image>
</view>
<view class="flex-center fs-24 app-fc-main SourceHanSansCN-Medium sex-item"
:class="[userInfo.sex === 2 ? 'active women' : '']" @click="onChange(2, 'sex')">
<image class="sex-item-img"
:src="userInfo.sex === 2 ? `${imgPrefix}whiteFemale.png` : `${imgPrefix}record-femaleImg.png`">
</image>
</view>
</view>
</form-cell>
</view>
<view class="footer">
<view class="footerBtn" @click="onsubmit()">
保存
</view>
<view class="bottom-safe-area"></view>
</view>
</view>
</template>
<script>
import FormCell from "../../../components/FormCell.vue";
import {
updateUserInfo,
getUserInfo
} from "../../../api/user";
import appConfig from "../../../constants/app.config";
import {
imgPrefix
} from "@/utils/common";
import {
uploadImageToOSS_PUT
} from "@/utils/oss";
export default {
components: {
FormCell,
},
data() {
return {
userInfo: {
head_pic_url: "",
head_pic: "",
nick_name: "",
birthday: "",
sex: 0,
},
appConfig,
imgPrefix
};
},
onShow() {
// 直接从 store缓存中获取用户信息并映射到表单字段
const storeUserInfo = this.$store.state?.user?.userInfo || {};
if (storeUserInfo && Object.keys(storeUserInfo).length > 0) {
// 将 gender 转换为 sex: "male" -> 1, "female" -> 2, 其他 -> 0
let sex = 0;
if (storeUserInfo.gender === 'male') {
sex = 1;
} else if (storeUserInfo.gender === 'female') {
sex = 2;
} else if (storeUserInfo.sex) {
// 兼容旧的 sex 字段
sex = storeUserInfo.sex;
}
// 格式化生日:将 ISO 8601 格式 (2006-01-02T00:00:00+08:00) 转换为 YYYY-MM-DD 格式
let birthday = storeUserInfo.birthday || '';
if (birthday) {
// 如果是 ISO 8601 格式,提取日期部分
if (birthday.includes('T')) {
birthday = birthday.split('T')[0];
}
// 确保格式为 YYYY-MM-DD
const dateMatch = birthday.match(/^(\d{4})-(\d{2})-(\d{2})/);
if (!dateMatch) {
// 如果不是标准格式,尝试转换
const date = new Date(birthday);
if (!isNaN(date.getTime())) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
birthday = `${year}-${month}-${day}`;
}
}
}
this.userInfo = {
head_pic_url: storeUserInfo.avatar || storeUserInfo.head_pic_url || storeUserInfo.head_pic || '',
head_pic: storeUserInfo.avatar || storeUserInfo.head_pic || storeUserInfo.head_pic_url || '',
nick_name: storeUserInfo.nickname || storeUserInfo.nick_name || storeUserInfo.username || '',
birthday: birthday,
sex: sex,
};
}
},
methods: {
// 保存
onsubmit() {
const {
head_pic,
nick_name,
birthday,
sex
} = this.userInfo;
if (!head_pic || !nick_name) {
uni.showToast({
icon: "none",
title: "请将昵称和头像填写完整",
});
return;
}
// 将 sex 转换为 gender: 1 -> "male", 2 -> "female", 其他 -> "other"
let gender = "other";
if (sex === 1) {
gender = "male";
} else if (sex === 2) {
gender = "female";
}
uni.showLoading({
title: "处理中..."
});
// 构建请求参数
const params = {
username: nick_name,
gender: gender,
birthday: birthday,
};
// 如果头像地址不是 https 开头,才传给后端
if (head_pic && !head_pic.startsWith('https://')) {
params.avatar = head_pic;
}
updateUserInfo(params).then(() => {
uni.hideLoading();
uni.navigateBack();
}).catch((err) => {
uni.hideLoading();
console.error('更新用户信息失败:', err);
});
},
// 更新头像
chooseavatar() {
let that = this;
uni.showLoading({
title: "上传中..."
});
uni.chooseImage({
count: 1, // 只选一张图片
sourceType: ['album', 'camera'], // 来源:相册、相机
success: async function(res) {
try {
const { url, objectKey } = await uploadImageToOSS_PUT(res.tempFilePaths[0]);
that.userInfo.head_pic_url = url; // 同时更新 head_pic_url因为模板使用的是这个字段
that.userInfo.head_pic = objectKey;
that.$forceUpdate();
uni.hideLoading();
uni.showToast({
title: "上传成功",
icon: "success",
});
} catch (error) {
console.error('头像上传失败:', error);
uni.hideLoading();
uni.showToast({
title: error?.message || "头像上传失败",
icon: "none"
});
}
},
fail: function(err) {
console.log('选择图片失败:', err.errMsg);
uni.hideLoading();
}
});
},
onChange(value, key) {
this.userInfo[key] = value;
this.$forceUpdate();
},
},
};
</script>
<style lang="scss">
.mine-user-edit {
background-color: #ffecf3;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: space-between;
.edit-content {
background-color: #fff;
border-radius: 16rpx;
padding: 0rpx 24rpx;
width: calc(100vw - 40rpx);
margin: 20rpx auto;
box-sizing: border-box;
.edit-cell {
border-bottom: 1rpx solid #ececec;
height: 110rpx;
width: 100%;
box-sizing: border-box;
.title {
color: #3D3D3D;
font-size: 24rpx;
.required {
color: #FF19A0;
}
}
.avator-icon {
width: 80rpx;
height: 80rpx;
border-radius: 80rpx;
background: gray;
}
.arrow-icon {
width: 11rpx;
height: 18rpx;
}
.edit-input {
height: 100%;
text-align: right;
flex: 1;
margin-left: 30rpx;
font-size: 24rpx;
}
}
.edit-sex {
width: 100%;
}
.sex-item {
width: 120rpx;
height: 64rpx;
background: #f9f7f9;
border-radius: 16rpx 16rpx 16rpx 16rpx;
margin-left: 50rpx;
&-img {
width: 28rpx;
height: 28rpx;
}
&.active {
color: #fff;
&.man {
background: #FF19A0;
}
&.women {
background: #FF19A0;
}
}
}
}
.user-avator {
margin: 0;
background: #fff;
border: 0;
padding: 0;
border-color: transparent;
padding-left: 100rpx;
&::after {
border: none;
}
}
.footer {
background-color: #fff;
border-radius: 32rpx 32rpx 0px 0px;
.footerBtn {
color: #fff;
background-color: #FF19A0;
width: calc(100% - 48rpx);
margin: auto;
margin-bottom: 24rpx;
margin-top: 12rpx;
border-radius: 100px;
text-align: center;
padding: 32rpx 0rpx;
}
.bottom-safe-area {
padding-bottom: constant(safe-area-inset-bottom);
/* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom);
/* 兼容 iOS >= 11.2 */
}
}
}
</style>