You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

287 lines
6.5 KiB

6 months ago
<template>
<view class="container">
<!-- 当前头像展示 -->
<view class="avatar-section">
<view class="current-avatar" @click="chooseImage">
2 months ago
<image :src="croppedImage?croppedImage:base.imgHost('logo-user.png')" />
6 months ago
<!-- <view v-else class="avatar-placeholder">
<text class="iconfont icon-user"></text>
</view> -->
</view>
<view class="avatar-tips">点击头像选择新照片</view>
</view>
<!-- 裁剪组件 -->
<!-- <u-cropper
v-if="showCropper"
:src="tempImage"
:width="300"
:height="300"
:scale="1"
:cut-width="300"
:cut-height="300"
:output-type="'jpg'"
:quality="0.9"
:max-width="600"
:max-height="600"
:show-cancel-btn="true"
:show-confirm-btn="true"
@cancel="cancelCrop"
@confirm="confirmCrop"
/> -->
<!-- 预览区 -->
2 months ago
<view v-if="croppedImage" class="crop-preview-wrap">
<view class="crop-preview">
<view class="preview-item">
<image :src="croppedImage" class="preview-circle small" mode="aspectFill" />
<view class="preview-label">小尺寸</view>
</view>
<view class="preview-item">
<image :src="croppedImage" class="preview-circle medium" mode="aspectFill" />
<view class="preview-label">中尺寸</view>
</view>
<view class="preview-item">
<image :src="croppedImage" class="preview-circle large" mode="aspectFill" />
<view class="preview-label">大尺寸</view>
</view>
6 months ago
</view>
2 months ago
<view class="form-btn">
<view @click="saveUser" type="primary">提交</view>
6 months ago
</view>
2 months ago
</view>
6 months ago
<qf-image-cropper ref="qfCropper" v-if="showCropper" :width="400" :height="400" :radius="200"
@crop="uploadSuccess" @close="closeCrop"></qf-image-cropper>
</view>
</template>
<script>
// 需在项目中安装 uCropper 组件https://ext.dcloud.net.cn/plugin?id=2713
import QfImageCropper from '@/uni_modules/qf-image-cropper/components/qf-image-cropper/qf-image-cropper.vue';
2 months ago
import {
ROOTPATH
6 months ago
} from '@/common/config'
export default {
components: {
QfImageCropper
},
data() {
return {
tempImage: '', // 临时选中的图片
croppedImage: '', // 裁剪后的图片
showCropper: false,
loading: false,
success: false
}
2 months ago
},
onLoad(){
this.croppedImage = this.vuex_user.headimgurl?this.vuex_user.headimgurl:''
console.log("this.vuex_user.headimgurl",this.vuex_user.headimgurl)
6 months ago
},
methods: {
chooseImage() {
uni.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: res => {
const filePath = res.tempFilePaths[0];
this.tempImage = filePath;
this.showCropper = true;
this.$nextTick(() => {
this.$refs.qfCropper?.resetData(); // 可选链操作符防止报错
this.$refs.qfCropper?.initImage(this.tempImage)
});
}
});
},
uploadSuccess(res) {
2 months ago
console.log("res", res)
6 months ago
this.saveAvatar(res.tempFilePath)
2 months ago
},
closeCrop(){
// this.croppedImage = ''
this.showCropper = false;
this.tempImage = '';
},
// 上传图片
6 months ago
// 更新userimg
async saveAvatar(file) {
2 months ago
if (!file) {
this.base.toast("请选择头像")
return
6 months ago
};
this.loading = true;
2 months ago
// 模拟上传
await uni.uploadFile({
url: ROOTPATH + "/api/mobile/upload-file",
filePath: file,
name: 'file',
header: {
['Authorization']: `Bearer ${this.vuex_token}`
},
success: (res) => {
console.log("res",res)
let data = JSON.parse(res.data)
6 months ago
this.croppedImage = data.url
this.showCropper = false;
2 months ago
this.tempImage = '';
}
})
6 months ago
2 months ago
},
async saveUser(files){
const res = await this.$u.api.saveUser({
headimgurl:this.croppedImage,
username:this.vuex_user.username
})
this.base.toast("更新成功",1500,function(){
setTimeout(function(){
uni.navigateBack()
},1500)
})
6 months ago
}
}
}
</script>
<style scoped lang="scss">
.container {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
display: flex;
flex-direction: column;
align-items: center;
padding-bottom: 40rpx;
}
.avatar-section {
background: rgba(255, 255, 255, 0.95);
border-radius: 40rpx;
padding: 60rpx 40rpx 30rpx 40rpx;
margin: 40rpx 0 20rpx 0;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
text-align: center;
width: 90vw;
max-width: 600rpx;
}
.current-avatar {
width: 240rpx;
height: 240rpx;
border-radius: 50%;
margin: 0 auto 30rpx;
overflow: hidden;
border: 8rpx solid #fff;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
position: relative;
background: #f0f0f0;
display: flex;
align-items: center;
justify-content: center;
}
.current-avatar image {
2 months ago
width: 240rpx;
6 months ago
height: 240rpx;
border-radius: 50%;
}
.avatar-placeholder {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: #bbb;
font-size: 100rpx;
}
.avatar-tips {
color: #666;
font-size: 26rpx;
margin-bottom: 10rpx;
}
.crop-preview-wrap {
width: 90vw;
max-width: 600rpx;
background: rgba(255, 255, 255, 0.95);
border-radius: 40rpx;
padding: 60rpx 40rpx 30rpx 40rpx;
margin: 40rpx 0 20rpx 0;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
background-color: #fff;
2 months ago
}
.crop-preview{
display: flex;
justify-content: center;
gap: 30rpx;
text-align: center;
6 months ago
}
.preview-item {
text-align: center;
}
.preview-circle {
border-radius: 50%;
overflow: hidden;
margin: 0 auto 8rpx;
border: 4rpx solid #e5e7eb;
}
.preview-circle.small {
width: 60rpx;
height: 60rpx;
}
.preview-circle.medium {
width: 80rpx;
height: 80rpx;
}
.preview-circle.large {
width: 120rpx;
height: 120rpx;
}
.preview-label {
font-size: 24rpx;
color: #6b7280;
}
.loading {
text-align: center;
padding: 40rpx;
color: #666;
}
.success-message {
background: #10b981;
color: white;
padding: 30rpx 40rpx;
border-radius: 20rpx;
margin: 30rpx 0;
text-align: center;
2 months ago
}
.form-btn {
width: 100%;
position: relative;
padding: 60rpx 0;
&>view {
width: 70%;
text-align: center;
margin: 0 auto;
color: #fff;
background: linear-gradient(to right, #5e5fbc, #0d0398);
border-radius: 30rpx;
padding: 20rpx;
}
6 months ago
}
</style>