Files
2026-09-29 15:17:13 +08:00

262 lines
5.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="profile-page">
<view class="profile-hero">
<AppNavbar class="profile-navbar" title="用户资料" show-back/>
<view class="intro-card">
<view class="card-title">
<view class="title-bar"></view>
<text>用户资料</text>
</view>
<text class="intro-text">点击头像上传,点击昵称获取微信昵称</text>
</view>
</view>
<view class="info-card">
<view class="card-title">
<view class="title-bar"></view>
<text>用户资料</text>
</view>
<view class="avatar-row">
<button class="ghost-btn" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
<u-avatar class="avatar-img" :src="form.avatar" mode="aspectFill" />
</button>
<view class="avatar-tip">点击头像上传</view>
</view>
</view>
<view class="info-card">
<view class="card-title">
<view class="title-bar"></view>
<text>姓名</text>
</view>
<view class="name-row">
<input v-model="form.realName" class="input" type="text" maxlength="20" placeholder="请输入姓名" />
</view>
</view>
<view class="info-card">
<view class="card-title">
<view class="title-bar"></view>
<text>昵称</text>
</view>
<view class="nickname-row">
<input v-model="form.nickname" class="input" type="nickname" placeholder="点击获取昵称" />
</view>
</view>
<view class="submit-btn" @tap="saveProfile">保存</view>
</view>
</template>
<script>
import {updateUserReq, userInfoReq} from "@/api/user";
import {chooseImg} from "@/util";
import {uploadImg} from "@/util";
import AppNavbar from "@/components/AppNavbar.vue";
export default {
components: {AppNavbar},
data() {
return {
defaultAvatar: '/static/logo.png',
form: {
avatar: '',
realName: '',
nickname: ''
},
saving: false
}
},
onShow() {
this.fetchUser()
},
methods: {
async fetchUser() {
const {data} = await userInfoReq()
this.form.avatar = data.avatar || data.avatarUrl || ''
this.form.realName = data.realName || data.real_name || data.name || ''
this.form.nickname = data.nickname || data.name || ''
},
async onChooseAvatar(e) {
const avatarUrl = e.detail && e.detail.avatarUrl
if (!avatarUrl) return
const res = await uploadImg(avatarUrl)
this.form.avatar = res.path
},
async pickAvatar() {
const res = await chooseImg(1)
if (!res.length) return
this.form.avatar = res[0].path
},
fetchWechatNickname() {
if (!uni.getUserProfile) {
uni.showToast({
title: '当前环境不支持',
icon: 'none'
})
return
}
uni.getUserProfile({
desc: '用于完善用户资料',
success: res => {
const info = res.userInfo || {}
if (info.nickName) this.form.nickname = info.nickName
},
fail: () => {
uni.showToast({
title: '获取失败',
icon: 'none'
})
}
})
},
async saveProfile() {
if (this.saving) return
if (!String(this.form.realName || '').trim()) {
uni.showToast({
title: '请填写姓名',
icon: 'none'
})
return
}
if (!this.form.nickname) {
uni.showToast({
title: '请填写昵称',
icon: 'none'
})
return
}
this.saving = true
try {
await updateUserReq({
avatar: this.form.avatar,
realName: String(this.form.realName || '').trim(),
nickname: this.form.nickname
})
uni.showToast({
title: '已保存',
icon: 'success'
})
} catch (err) {
uni.showToast({
title: '保存失败',
icon: 'none'
})
} finally {
this.saving = false
}
}
}
}
</script>
<style lang="scss" scoped>
.profile-page {
min-height: 100vh;
//padding: 0 20rpx 60rpx;
background: #f5f5f5;
}
.profile-hero {
//padding: 30rpx 6rpx 18rpx;
//background: url('https://yaodongxiao.oss-cn-guangzhou.aliyuncs.com/20260126/462bfa04cf0eff8698884c38b9d17519.png') no-repeat
// top center / 100% auto;
}
.intro-card {
margin: 18rpx 20rpx 0;
padding: 20rpx 18rpx;
border-radius: 20rpx;
background: rgba(255, 255, 255, 0.9);
box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.08);
}
.card-title {
display: flex;
align-items: center;
gap: 12rpx;
font-size: 28rpx;
font-weight: 700;
color: #1f2937;
}
.title-bar {
width: 6rpx;
height: 30rpx;
border-radius: 999rpx;
background: #2fc6a7;
}
.intro-text {
margin-top: 12rpx;
font-size: 26rpx;
color: #6b7280;
line-height: 1.6;
}
.info-card {
margin: 16rpx 20rpx 0;
padding: 18rpx;
border-radius: 20rpx;
background: #ffffff;
box-shadow: 0 8rpx 16rpx rgba(0, 0, 0, 0.06);
}
.avatar-row {
margin-top: 16rpx;
display: flex;
align-items: center;
justify-content: space-between;
}
.avatar-img {
width: 140rpx;
height: 140rpx;
border-radius: 50%;
background: #f5f7fb;
}
.avatar-tip {
color: #6b7280;
font-size: 26rpx;
}
.ghost-btn {
margin: 0;
border: none;
border-radius: 999rpx;
padding: 0;
background: transparent;
}
.ghost-btn::after {
border: none;
}
.nickname-row {
margin-top: 16rpx;
}
.name-row {
margin-top: 16rpx;
}
.input {
font-size: 28rpx;
color: #6b7280;
}
.submit-btn {
margin: 24rpx 20rpx 0;
padding: 18rpx 0;
text-align: center;
border-radius: 999rpx;
background: linear-gradient(135deg, #33d0b3, #22c3a1);
color: #ffffff;
font-size: 30rpx;
font-weight: 700;
box-shadow: 0 10rpx 18rpx rgba(34, 195, 161, 0.3);
}
</style>