New file |
| | |
| | | <template> |
| | | <view class="edit-profile-container"> |
| | | <!-- 头部标题 --> |
| | | <view class="header"> |
| | | <text class="title">编辑资料</text> |
| | | </view> |
| | | |
| | | <!-- 表单区域 --> |
| | | <view class="form-container"> |
| | | <!-- 头像上传 --> |
| | | <view class="form-item"> |
| | | <text class="label">头像</text> |
| | | <view class="avatar-upload" @click="chooseAvatar"> |
| | | <image class="avatar" :src="formData.avatar" mode="aspectFill"></image> |
| | | <view class="upload-tip">点击修改</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 昵称 --> |
| | | <view class="form-item"> |
| | | <text class="label">昵称</text> |
| | | <input |
| | | class="input" |
| | | type="nickname" |
| | | v-model="formData.nickName" |
| | | placeholder="请输入昵称" |
| | | @blur="validateNickname" |
| | | /> |
| | | </view> |
| | | |
| | | <!-- 签名 --> |
| | | <view class="form-item"> |
| | | <text class="label">签名</text> |
| | | <textarea |
| | | class="textarea" |
| | | v-model="formData.motto" |
| | | placeholder="介绍一下自己吧~" |
| | | maxlength="50" |
| | | auto-height |
| | | /> |
| | | <text class="word-count">{{ formData.motto.length }}/50</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 保存按钮 --> |
| | | <view class="btn-container"> |
| | | <button |
| | | class="save-btn" |
| | | :disabled="isSaving" |
| | | @click="saveInfo" |
| | | > |
| | | {{ isSaving ? '保存中...' : '保存修改' }} |
| | | </button> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getSTSToken, getFilePreviewUrl } from "@/api/common.js"; |
| | | import { saveVideoHomeInfo } from "@/api/user.js"; |
| | | import { getFileKey } from "@/utils/file.js"; |
| | | export default { |
| | | data() { |
| | | return { |
| | | formData: { |
| | | avatar: '', |
| | | nickName: '', |
| | | motto: '', |
| | | authorId: '' |
| | | }, |
| | | isSaving: false, |
| | | bucket: '', |
| | | region: '', |
| | | cosClient: null |
| | | } |
| | | }, |
| | | onShow() { |
| | | this.initCOS(); |
| | | }, |
| | | onLoad(option) { |
| | | this.formData.authorId = option.authorId; |
| | | this.formData.avatar = option.avatar; |
| | | this.formData.nickName = option.nickName; |
| | | this.formData.motto = option.motto ? option.motto : ''; |
| | | }, |
| | | methods: { |
| | | initCOS() { |
| | | // 调用后端获取sts临时访问凭证 |
| | | getSTSToken().then(res => { |
| | | const COS = require('@/lib/cos-wx-sdk-v5.js'); // 开发时使用 |
| | | // const COS = require('./lib/cos-wx-sdk-v5.min.js'); // 上线时使用压缩包 |
| | | |
| | | // console.log(COS.version); sdk 版本需要不低于 1.7.2 |
| | | this.cosClient = new COS({ |
| | | SecretId: res.data.data.tmpSecretId, // sts 服务下发的临时 secretId |
| | | SecretKey: res.data.data.tmpSecretKey, // sts 服务下发的临时 secretKey |
| | | SecurityToken: res.data.data.sessionToken, // sts 服务下发的临时 SessionToken |
| | | StartTime: res.data.data.stsStartTime, // 建议传入服务端时间,可避免客户端时间不准导致的签名错误 |
| | | ExpiredTime: res.data.data.stsEndTime, // 临时密钥过期时间 |
| | | SimpleUploadMethod: 'putObject', // 强烈建议,高级上传、批量上传内部对小文件做简单上传时使用 putObject,sdk 版本至少需要v1.3.0 |
| | | }); |
| | | this.bucket = res.data.data.bucket |
| | | this.region = res.data.data.region |
| | | }) |
| | | }, |
| | | // 选择头像 |
| | | chooseAvatar() { |
| | | uni.chooseImage({ |
| | | count: 1, |
| | | sizeType: ['compressed'], |
| | | sourceType: ['album', 'camera'], |
| | | success: (res) => { |
| | | const tempPath = res.tempFilePaths[0]; |
| | | // 获取文件名 |
| | | let fileName = tempPath.substring(tempPath.lastIndexOf('/') + 1); |
| | | // 处理安卓可能的URI编码 |
| | | if(fileName.indexOf('%') > -1) { |
| | | fileName = decodeURIComponent(fileName); |
| | | } |
| | | const fileKey = getFileKey(fileName); |
| | | this.cosClient.uploadFile({ |
| | | Bucket: this.bucket, |
| | | Region: this.region, |
| | | Key: fileKey, |
| | | FilePath: tempPath, |
| | | SliceSize: 1024 * 1024 * 5, /* 触发分块上传的阈值,5M */ |
| | | }, (err, data) => { |
| | | if (err) { |
| | | console.log('上传失败', err); |
| | | this.formData.avatar = '' |
| | | uni.showToast({ |
| | | title: '图片上传失败', |
| | | icon: 'none' |
| | | }); |
| | | } else { |
| | | getFilePreviewUrl(fileKey).then(res => { |
| | | this.formData.avatar = res.data.data |
| | | }) |
| | | } |
| | | }); |
| | | }, |
| | | fail: (err) => { |
| | | console.error('选择图片失败:', err); |
| | | uni.showToast({ |
| | | title: '选择图片失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | // 验证昵称 |
| | | validateNickname() { |
| | | if (!this.formData.nickName.trim()) { |
| | | uni.showToast({ title: '昵称不能为空', icon: 'none' }); |
| | | return false; |
| | | } |
| | | if (this.formData.nickName.length > 12) { |
| | | uni.showToast({ title: '昵称不能超过12个字符', icon: 'none' }); |
| | | return false; |
| | | } |
| | | return true; |
| | | }, |
| | | |
| | | // 保存个人信息 |
| | | async saveInfo() { |
| | | this.isSaving = true; |
| | | if(this.validateNickname()) { |
| | | saveVideoHomeInfo(this.formData).then(res => { |
| | | uni.showToast({ |
| | | title: '保存成功', |
| | | icon: 'success' |
| | | }); |
| | | // 返回上级页面 |
| | | uni.navigateBack({ |
| | | delta: 1 |
| | | }); |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .edit-profile-container { |
| | | padding: 20rpx 30rpx; |
| | | min-height: 100vh; |
| | | background-color: #f7f7f7; |
| | | } |
| | | |
| | | .header { |
| | | padding: 30rpx 0; |
| | | .title { |
| | | font-size: 36rpx; |
| | | font-weight: bold; |
| | | color: #333; |
| | | } |
| | | } |
| | | |
| | | .form-container { |
| | | background-color: #fff; |
| | | border-radius: 16rpx; |
| | | padding: 0 30rpx; |
| | | margin-bottom: 40rpx; |
| | | } |
| | | |
| | | .form-item { |
| | | padding: 30rpx 0; |
| | | border-bottom: 1rpx solid #f2f2f2; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | &:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .label { |
| | | font-size: 30rpx; |
| | | color: #333; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | } |
| | | |
| | | .avatar-upload { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .avatar { |
| | | width: 120rpx; |
| | | height: 120rpx; |
| | | border-radius: 50%; |
| | | margin-right: 30rpx; |
| | | } |
| | | |
| | | .upload-tip { |
| | | color: #999; |
| | | font-size: 26rpx; |
| | | } |
| | | } |
| | | |
| | | .input { |
| | | height: 80rpx; |
| | | font-size: 28rpx; |
| | | color: #333; |
| | | } |
| | | |
| | | .textarea { |
| | | width: 100%; |
| | | min-height: 120rpx; |
| | | font-size: 28rpx; |
| | | color: #333; |
| | | padding: 10rpx 0; |
| | | } |
| | | |
| | | .word-count { |
| | | align-self: flex-end; |
| | | font-size: 24rpx; |
| | | color: #999; |
| | | margin-top: 10rpx; |
| | | } |
| | | |
| | | .btn-container { |
| | | padding: 0 30rpx; |
| | | |
| | | .save-btn { |
| | | background-color: #07c160; |
| | | color: #fff; |
| | | border-radius: 50rpx; |
| | | font-size: 32rpx; |
| | | |
| | | &[disabled] { |
| | | background-color: #cccccc; |
| | | color: #fff; |
| | | opacity: 0.7; |
| | | } |
| | | } |
| | | } |
| | | </style> |