Files

273 lines
5.5 KiB
Vue
Raw Permalink Normal View History

2025-11-24 15:30:05 +08:00
<template>
<view class="edit-user-info">
<!-- 顶部导航栏 -->
<view class="nav-bar">
<view class="nav-back" @click="goBack">
<uni-icons type="arrowleft" size="24" color="#fff"></uni-icons>
</view>
<view class="nav-title">编辑用户信息</view>
<view class="nav-save" @click="saveUserInfo">
<text>保存</text>
</view>
</view>
<!-- 用户信息表单 -->
<view class="user-form">
<!-- 头像编辑 -->
<view class="avatar-section">
<view class="avatar-label">头像</view>
<view class="avatar-content">
<view class="avatar-upload" @click="updateAvatar">
<image class="avatar-preview" :src="userInfo.avatar" mode="aspectFit"></image>
<view class="avatar-mask">
<uni-icons type="camera" size="24" color="#fff"></uni-icons>
</view>
</view>
<text class="avatar-tip">点击更新头像</text>
</view>
</view>
<!-- 昵称编辑 -->
<view class="nickname-section">
<view class="nickname-label">昵称</view>
<view class="nickname-content">
<input
class="nickname-input"
type="text"
placeholder="请输入昵称"
v-model="userInfo.nickname"
maxlength="20"
/>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, onMounted } from 'vue'
// 用户信息
const userInfo = ref({
nickname: '',
avatar: ''
})
// 组件挂载时加载用户信息
onMounted(() => {
loadUserInfo()
})
// 加载用户信息
const loadUserInfo = () => {
const savedUserInfo = uni.getStorageSync('userInfo')
if (savedUserInfo) {
userInfo.value = savedUserInfo
} else {
// 默认用户信息
userInfo.value = {
nickname: '666',
avatar: 'https://ts1.tc.mm.bing.net/th/id/OIP-C.QQG4bvcAR3CJ0WeQULA9UQAAAA?w=275&h=211&c=8&rs=1&qlt=90&o=6&cb=ucfimgc1&dpr=1.5&pid=3.1&rm=2'
}
}
}
// 更新头像
const updateAvatar = () => {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
const tempFilePath = res.tempFilePaths[0]
userInfo.value.avatar = tempFilePath
uni.showToast({
title: '头像更新成功',
icon: 'success'
})
},
fail: (err) => {
console.log('选择头像失败:', err)
uni.showToast({
title: '选择头像失败',
icon: 'none'
})
}
})
}
// 保存用户信息
const saveUserInfo = () => {
if (!userInfo.value.nickname.trim()) {
uni.showToast({
title: '请输入昵称',
icon: 'none'
})
return
}
// 保存到本地存储
uni.setStorageSync('userInfo', userInfo.value)
// 同时更新玩家数据中的自己信息
const players = uni.getStorageSync('players') || []
const selfPlayer = players.find(player => player.isSelf)
if (selfPlayer) {
selfPlayer.name = userInfo.value.nickname
selfPlayer.avatar = userInfo.value.avatar
uni.setStorageSync('players', players)
}
uni.showToast({
title: '保存成功',
icon: 'success'
})
// 触发全局事件,通知其他页面更新
uni.$emit('userInfoUpdated')
// 延迟返回,确保事件被处理
setTimeout(() => {
uni.navigateBack({
delta: 1
})
}, 1000)
}
// 返回上一页
const goBack = () => {
uni.navigateBack()
}
</script>
<style lang="less" scoped>
.edit-user-info {
background-color: #fff;
min-height: 100vh;
}
/* 顶部导航栏 */
.nav-bar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 30rpx;
background-color: #41479b;
color: #fff;
.nav-back, .nav-save {
width: 120rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
}
.nav-save text {
font-size: 32rpx;
font-weight: 500;
}
.nav-title {
font-size: 32rpx;
font-weight: 500;
}
}
/* 用户信息表单 */
.user-form {
padding: 40rpx 30rpx;
}
/* 头像编辑区域 */
.avatar-section {
display: flex;
align-items: flex-start;
margin-bottom: 60rpx;
padding-bottom: 40rpx;
border-bottom: 1rpx solid #eee;
.avatar-label {
width: 120rpx;
font-size: 32rpx;
color: #000;
font-weight: 500;
}
.avatar-content {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
}
.avatar-upload {
position: relative;
width: 160rpx;
height: 160rpx;
border-radius: 50%;
overflow: hidden;
margin-bottom: 20rpx;
.avatar-preview {
width: 100%;
height: 100%;
border-radius: 50%;
}
.avatar-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s;
}
&:active .avatar-mask {
opacity: 1;
}
}
.avatar-tip {
font-size: 28rpx;
color: #666;
}
}
/* 昵称编辑区域 */
.nickname-section {
display: flex;
align-items: center;
.nickname-label {
width: 120rpx;
font-size: 32rpx;
color: #000;
font-weight: 500;
}
.nickname-content {
flex: 1;
}
.nickname-input {
width: 100%;
height: 80rpx;
border: 1rpx solid #ddd;
border-radius: 8rpx;
padding: 0 20rpx;
font-size: 32rpx;
&:focus {
border-color: #41479b;
}
}
}
</style>