diff --git a/package.json b/package.json index de73668..7a54d23 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "protobufjs": "^7.4.0", "uuid": "^10.0.0", "vue": "^3.4.29", + "vue-cropper": "^1.1.1", "vue-router": "^4.3.3" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 12d11c5..529f8a5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,6 +38,9 @@ importers: vue: specifier: ^3.4.29 version: 3.4.38 + vue-cropper: + specifier: ^1.1.1 + version: 1.1.1 vue-router: specifier: ^4.3.3 version: 4.4.3(vue@3.4.38) @@ -1603,6 +1606,9 @@ packages: terser: optional: true + vue-cropper@1.1.1: + resolution: {integrity: sha512-WsqKMpaBf9Osi1LQlE/5AKdD0nHWOy1asLXocaG8NomOWO07jiZi968+/PbMmnD0QbPJOumDQaGuGa13qys85A==} + vue-demi@0.14.10: resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} engines: {node: '>=12'} @@ -3145,6 +3151,8 @@ snapshots: fsevents: 2.3.3 sass: 1.77.8 + vue-cropper@1.1.1: {} + vue-demi@0.14.10(vue@3.4.38): dependencies: vue: 3.4.38 diff --git a/src/views/setting/components/EditeAvatar.vue b/src/views/setting/components/EditeAvatar.vue index fce850e..5a9e67e 100644 --- a/src/views/setting/components/EditeAvatar.vue +++ b/src/views/setting/components/EditeAvatar.vue @@ -2,57 +2,74 @@ import { ref } from 'vue' import { userStore } from '@/stores' import { Plus, Upload } from '@element-plus/icons-vue' -import selectAvatar from '@/assets/select_avatar.jpg' import { userUploadAvatarService } from '@/api/user' import { ElMessage } from 'element-plus' +import 'vue-cropper/dist/index.css' +import { VueCropper } from 'vue-cropper' defineProps(['modelValue']) const emit = defineEmits(['update:modelValue', 'update:newAvatar']) const userData = userStore() const uploadRef = ref() -const imgUrl = ref(userData.user.avatar) +const cropper = ref() +const img = ref('') +const previewImg = ref('') const isLoading = ref(false) -let selectedFile - -const onSelected = (file) => { - imgUrl.value = URL.createObjectURL(file.raw) - selectedFile = file.raw -} - -const onSuccess = () => {} - -const beforeUpload = () => {} - -const onUpload = async () => { - if (!selectedFile) { - ElMessage.warning('您还未选择新头像!') - return - } - - isLoading.value = true - try { - const res = await userUploadAvatarService({ file: selectedFile }) - emit('update:newAvatar', res.data.data) - emit('update:modelValue', false) - selectedFile = null - ElMessage.success('头像上传成功') - } catch (error) { - /* empty */ - } finally { - isLoading.value = false - } -} +const fileName = ref('') // 打开的时候触发 const onOpen = () => { - imgUrl.value = userData.user.avatar + fileName.value = userData.user.avatar?.split('/').pop() + img.value = userData.user.avatar + previewImg.value = img.value } // 关闭的时候触发 const onClose = () => { isLoading.value = false } + +// 选择了文件触发 +const onSelected = (file) => { + fileName.value = file.name + img.value = URL.createObjectURL(file.raw) + previewImg.value = img.value +} + +const onUpload = async () => { + cropper.value.getCropBlob(async (blob) => { + const lastDotIndex = fileName.value.lastIndexOf('.') + const prefix = fileName.value.substring(0, lastDotIndex) + const suffix = fileName.value.substring(lastDotIndex) + let file = new File( + [blob], + `${prefix}_${cropper.value.cropW}x${cropper.value.cropH}${suffix}`, + { + type: blob.type, + lastModified: Date.now() + } + ) + + isLoading.value = true + try { + const res = await userUploadAvatarService({ file: file }) + emit('update:newAvatar', res.data.data) + emit('update:modelValue', false) + ElMessage.success('头像上传成功') + } catch (error) { + /* empty */ + } finally { + isLoading.value = false + } + }) +} + +const stopCrop = () => { + cropper.value.getCropData((data) => { + previewImg.value = data + }) +}