|
|
@@ -0,0 +1,261 @@
|
|
|
+<template>
|
|
|
+ <view class="edit-profile-container">
|
|
|
+ <view class="edit-header">
|
|
|
+ <text class="header-title">编辑资料</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="edit-form">
|
|
|
+ <!-- 头像 -->
|
|
|
+ <view class="form-item">
|
|
|
+ <text class="item-label">头像</text>
|
|
|
+ <button class="avatar-btn" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
|
|
|
+ <image class="avatar-preview" :src="avatarUrl" mode="aspectFill"></image>
|
|
|
+ <text class="change-text">点击更换</text>
|
|
|
+ </button>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 昵称 -->
|
|
|
+ <view class="form-item">
|
|
|
+ <text class="item-label">昵称</text>
|
|
|
+ <input
|
|
|
+ class="item-input"
|
|
|
+ type="nickname"
|
|
|
+ v-model="nickname"
|
|
|
+ placeholder="请输入昵称"
|
|
|
+ maxlength="20"
|
|
|
+ />
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 手机号(只读) -->
|
|
|
+ <view class="form-item" v-if="phone">
|
|
|
+ <text class="item-label">手机号</text>
|
|
|
+ <text class="item-value">{{ phone }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 保存按钮 -->
|
|
|
+ <view class="action-area">
|
|
|
+ <button class="save-btn" @click="handleSave">保存</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { getUserInfo, setUserInfo } from '@/utils/auth.js'
|
|
|
+import { updateUserProfile } from '@/utils/api.js'
|
|
|
+
|
|
|
+export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ avatarUrl: '/static/images/head.png',
|
|
|
+ nickname: '',
|
|
|
+ phone: '',
|
|
|
+ originalAvatar: '',
|
|
|
+ originalNickname: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ onLoad() {
|
|
|
+ this.loadUserInfo()
|
|
|
+ },
|
|
|
+
|
|
|
+ methods: {
|
|
|
+ /**
|
|
|
+ * 加载用户信息
|
|
|
+ */
|
|
|
+ loadUserInfo() {
|
|
|
+ const userInfo = getUserInfo()
|
|
|
+ if (userInfo) {
|
|
|
+ this.avatarUrl = userInfo.avatar || '/static/images/head.png'
|
|
|
+ this.nickname = userInfo.nickname || ''
|
|
|
+ this.phone = userInfo.phone || ''
|
|
|
+ this.originalAvatar = this.avatarUrl
|
|
|
+ this.originalNickname = this.nickname
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 选择头像
|
|
|
+ */
|
|
|
+ onChooseAvatar(e) {
|
|
|
+ const { avatarUrl } = e.detail
|
|
|
+ this.avatarUrl = avatarUrl
|
|
|
+ console.log('选择头像:', avatarUrl)
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存资料
|
|
|
+ */
|
|
|
+ async handleSave() {
|
|
|
+ if (!this.nickname || this.nickname.trim() === '') {
|
|
|
+ uni.showToast({
|
|
|
+ title: '请输入昵称',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否有修改
|
|
|
+ if (this.avatarUrl === this.originalAvatar && this.nickname === this.originalNickname) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '没有修改',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ uni.showLoading({ title: '保存中...' })
|
|
|
+
|
|
|
+ // 上传头像(如果更换了头像且不是默认头像)
|
|
|
+ let uploadedAvatarUrl = this.avatarUrl
|
|
|
+ if (this.avatarUrl !== this.originalAvatar && !this.avatarUrl.startsWith('/static/')) {
|
|
|
+ // TODO: 这里需要上传头像到服务器
|
|
|
+ // 暂时直接使用微信临时路径
|
|
|
+ uploadedAvatarUrl = this.avatarUrl
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调用后端接口更新用户信息
|
|
|
+ const result = await updateUserProfile({
|
|
|
+ nickname: this.nickname,
|
|
|
+ avatar: uploadedAvatarUrl
|
|
|
+ })
|
|
|
+
|
|
|
+ console.log('更新成功:', result)
|
|
|
+
|
|
|
+ // 更新本地存储的用户信息
|
|
|
+ const userInfo = getUserInfo()
|
|
|
+ userInfo.nickname = this.nickname
|
|
|
+ userInfo.avatar = uploadedAvatarUrl
|
|
|
+ setUserInfo(userInfo)
|
|
|
+
|
|
|
+ uni.hideLoading()
|
|
|
+ uni.showToast({
|
|
|
+ title: '保存成功',
|
|
|
+ icon: 'success'
|
|
|
+ })
|
|
|
+
|
|
|
+ // 延迟返回
|
|
|
+ setTimeout(() => {
|
|
|
+ uni.navigateBack()
|
|
|
+ }, 1500)
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('保存失败:', error)
|
|
|
+ uni.hideLoading()
|
|
|
+ uni.showToast({
|
|
|
+ title: error.message || '保存失败',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.edit-profile-container {
|
|
|
+ min-height: 100vh;
|
|
|
+ background: #f5f6fb;
|
|
|
+ padding: 30rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.edit-header {
|
|
|
+ text-align: center;
|
|
|
+ padding: 40rpx 0;
|
|
|
+}
|
|
|
+
|
|
|
+.header-title {
|
|
|
+ font-size: 40rpx;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #222;
|
|
|
+}
|
|
|
+
|
|
|
+.edit-form {
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 20rpx;
|
|
|
+ padding: 40rpx;
|
|
|
+ margin-bottom: 40rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.form-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 30rpx 0;
|
|
|
+ border-bottom: 1rpx solid #f0f0f0;
|
|
|
+}
|
|
|
+
|
|
|
+.form-item:last-child {
|
|
|
+ border-bottom: none;
|
|
|
+}
|
|
|
+
|
|
|
+.item-label {
|
|
|
+ width: 150rpx;
|
|
|
+ font-size: 32rpx;
|
|
|
+ color: #333;
|
|
|
+ font-weight: 500;
|
|
|
+}
|
|
|
+
|
|
|
+.avatar-btn {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ background: transparent;
|
|
|
+ border: none;
|
|
|
+ padding: 0;
|
|
|
+ margin: 0;
|
|
|
+ line-height: normal;
|
|
|
+}
|
|
|
+
|
|
|
+.avatar-btn::after {
|
|
|
+ border: none;
|
|
|
+}
|
|
|
+
|
|
|
+.avatar-preview {
|
|
|
+ width: 120rpx;
|
|
|
+ height: 120rpx;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: #f0f0f0;
|
|
|
+}
|
|
|
+
|
|
|
+.change-text {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #5d55e8;
|
|
|
+}
|
|
|
+
|
|
|
+.item-input {
|
|
|
+ flex: 1;
|
|
|
+ height: 80rpx;
|
|
|
+ font-size: 32rpx;
|
|
|
+ color: #333;
|
|
|
+ text-align: right;
|
|
|
+}
|
|
|
+
|
|
|
+.item-value {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 32rpx;
|
|
|
+ color: #999;
|
|
|
+ text-align: right;
|
|
|
+}
|
|
|
+
|
|
|
+.action-area {
|
|
|
+ padding: 0 40rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.save-btn {
|
|
|
+ width: 100%;
|
|
|
+ height: 90rpx;
|
|
|
+ background: linear-gradient(135deg, #5d55e8, #7568ff);
|
|
|
+ color: #fff;
|
|
|
+ font-size: 32rpx;
|
|
|
+ border-radius: 45rpx;
|
|
|
+ border: none;
|
|
|
+ box-shadow: 0 12rpx 24rpx rgba(93, 85, 232, 0.4);
|
|
|
+ line-height: 90rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.save-btn:active {
|
|
|
+ opacity: 0.9;
|
|
|
+}
|
|
|
+</style>
|