使用cropperjs替换vue-cropper

修复上传头像失败的问题

代码优化
master
toesbieya 6 years ago
parent ce2bf95904
commit eda8fd5145
  1. 5
      vue/full/package-lock.json
  2. 1
      vue/full/package.json
  3. 2
      vue/full/src/globalMethod/Verify/main.vue
  4. 6
      vue/full/src/globalMethod/Verify/style.scss
  5. 6
      vue/full/src/util/element-ui/elTree.js
  6. 2
      vue/full/src/util/observable.js
  7. 134
      vue/full/src/view/admin/userCenter/component/Avatar.vue

@ -13591,11 +13591,6 @@
"resolved": "https://registry.npmjs.org/vue-count-to/-/vue-count-to-1.0.13.tgz", "resolved": "https://registry.npmjs.org/vue-count-to/-/vue-count-to-1.0.13.tgz",
"integrity": "sha512-6R4OVBVNtQTlcbXu6SJ8ENR35M2/CdWt3Jmv57jOUM+1ojiFmjVGvZPH8DfHpMDSA+ITs+EW5V6qthADxeyYOQ==" "integrity": "sha512-6R4OVBVNtQTlcbXu6SJ8ENR35M2/CdWt3Jmv57jOUM+1ojiFmjVGvZPH8DfHpMDSA+ITs+EW5V6qthADxeyYOQ=="
}, },
"vue-cropper": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/vue-cropper/-/vue-cropper-0.5.4.tgz",
"integrity": "sha512-9wwHOk1eHdl+nyq2fnIFDeDMjaXPh1dqfY+FdeEGU7Z/cKVOyH0pLrW0/5NH3xnRzqrU3DAQ8LjC/9/eHdvqKA=="
},
"vue-hot-reload-api": { "vue-hot-reload-api": {
"version": "2.3.4", "version": "2.3.4",
"resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",

@ -21,7 +21,6 @@
"socket.io-client": "^2.3.0", "socket.io-client": "^2.3.0",
"vue": "^2.6.11", "vue": "^2.6.11",
"vue-count-to": "^1.0.13", "vue-count-to": "^1.0.13",
"vue-cropper": "^0.5.4",
"vue-router": "^3.3.4", "vue-router": "^3.3.4",
"vuex": "^3.4.0" "vuex": "^3.4.0"
}, },

@ -3,7 +3,7 @@
<div <div
v-show="visible" v-show="visible"
class="puzzle-container" class="puzzle-container"
:class="{'puzzle-shake':stat==='fail'}" :class="{'is-error': stat === 'fail'}"
:style="`left: ${positionLeft}px;top: ${positionTop}px;`" :style="`left: ${positionLeft}px;top: ${positionTop}px;`"
> >
<div class="puzzle-view" :style="`width:${width}px;height:${height}px;`"> <div class="puzzle-view" :style="`width:${width}px;height:${height}px;`">

@ -57,8 +57,6 @@
padding-top: 10%; padding-top: 10%;
&__icon { &__icon {
/*background-size: 764.70588%;
background-position: 0 70.70218%;*/
background-image: url(./image/loading.png); background-image: url(./image/loading.png);
margin: 11% auto 10px; margin: 11% auto 10px;
width: 34px; width: 34px;
@ -197,9 +195,8 @@
} }
} }
} }
}
.puzzle-shake { &.is-error {
animation: shake 0.2s linear 3 both; animation: shake 0.2s linear 3 both;
} }
@ -214,3 +211,4 @@
transform: translate3d(0, 0, 0) transform: translate3d(0, 0, 0)
} }
} }
}

@ -4,13 +4,11 @@
* @param ref el-tree实例 * @param ref el-tree实例
* @param action 'expand' | 'collapse' * @param action 'expand' | 'collapse'
* @param level 展开的节点最大深度为0时匹配全部节点 * @param level 展开的节点最大深度为0时匹配全部节点
* @param func 自定义展开的函数传入一个node返回boolean优先使用 * @param func 自定义展开的函数传入(node, index)返回boolean优先使用
*/ */
export function expandControl(ref, action = 'expand', level = 1, func) { export function expandControl(ref, action = 'expand', level = 1, func) {
const handler = function () { const handler = function () {
if (typeof func === 'function') { if (typeof func === 'function') return func
return node => func(node)
}
const expand = action === 'expand' const expand = action === 'expand'
const forAll = level === 0 const forAll = level === 0

@ -18,7 +18,7 @@ export function createGetters(store) {
return getters return getters
} }
//设置mutation //为Vue.observer返回的对象设置mutation
export function createMutations(store, all = false) { export function createMutations(store, all = false) {
const keys = Object.keys(store) const keys = Object.keys(store)
const obj = {} const obj = {}

@ -1,37 +1,27 @@
<template> <template>
<abstract-dialog :loading="loading" title="上传头像" :value="value" width="50%" @close="cancel"> <abstract-dialog :loading="loading" title="上传头像" :value="value" width="50%" @close="clear">
<div class="avatar-cropper"> <div class="avatar-cropper cropper-bg">
<vue-cropper <div v-show="!img" class="avatar-cropper-bg cropper-bg" title="选择图片" @click="handleBgClick"/>
ref="cropper"
:img="img" <img :src="img">
:info="false"
autoCrop
autoCropHeight="200px"
autoCropWidth="200px"
fixedBox
full
outputType="png"
@wheel.native.prevent="scale"
/>
<input <input
ref="input" ref="input"
accept="image/png, image/jpeg, image/gif, image/jpg" accept="image/png, image/jpeg, image/gif, image/jpg"
type="file" type="file"
@change="chooseImage" @change="onInputChange"
> >
</div> </div>
<template v-slot:footer> <template v-slot:footer>
<el-button plain size="small" @click="$refs.input.click()">选择图片</el-button> <el-button plain size="small" @click="chooseImage">选择图片</el-button>
<el-button plain size="small" @click="closeDialog"> </el-button> <el-button plain size="small" @click="closeDialog"> </el-button>
<el-button size="small" type="primary" @click="confirm"> </el-button> <el-button :loading="loading" size="small" type="primary" @click="confirm"> </el-button>
</template> </template>
</abstract-dialog> </abstract-dialog>
</template> </template>
<script> <script>
import {VueCropper} from 'vue-cropper'
import AbstractDialog from '@/component/abstract/Dialog' import AbstractDialog from '@/component/abstract/Dialog'
import dialogMixin from "@/mixin/dialogMixin" import dialogMixin from "@/mixin/dialogMixin"
import {elError, elSuccess} from "@/util/message" import {elError, elSuccess} from "@/util/message"
@ -43,7 +33,7 @@ export default {
mixins: [dialogMixin], mixins: [dialogMixin],
components: {VueCropper, AbstractDialog}, components: {AbstractDialog},
props: { props: {
value: Boolean value: Boolean
@ -53,31 +43,35 @@ export default {
return { return {
loading: false, loading: false,
img: '', img: '',
name: '' name: '',
type: ''
} }
}, },
methods: { methods: {
//
handleBgClick() {
!this.img && this.chooseImage()
},
clear() { clear() {
this.loading = false this.loading = false
this.$refs.cropper.clearCrop() this.cropper && this.cropper.destroy()
this.img && window.URL.revokeObjectURL(this.img) this.img && window.URL.revokeObjectURL(this.img)
this.img = '' this.img = ''
this.name = '' this.name = ''
this.type = ''
}, },
scale(e) { onInputChange(e) {
const eventDelta = e.wheelDelta || -(e.detail || 0) * 40
this.$refs.cropper.changeScale(eventDelta / 120)
},
chooseImage(e) {
if (this.loading) return if (this.loading) return
this.clear() this.clear()
const file = e.target.files[0] const file = e.target.files[0]
if (!file) return
if (!file.type.includes('image')) { if (!file.type.includes('image')) {
return elError('请上传图片') return elError('请上传图片')
} }
@ -87,50 +81,104 @@ export default {
} }
this.name = file.name this.name = file.name
const reader = new FileReader() this.type = file.type
reader.onload = e => { this.img = window.URL.createObjectURL(file)
this.img = window.URL.createObjectURL(new Blob([e.target.result]))
//使nextTickimgsrc
this.$nextTick(() => {
this.cropper = new window.Cropper(
this.$el.querySelector('.avatar-cropper > img'),
{
dragMode: 'move',
initialAspectRatio: 1,
aspectRatio: 1,
checkCrossOrigin: false,
checkOrientation: false,
guides: false,
center: false,
rotatable: false,
cropBoxResizable: false,
toggleDragModeOnDblclick: false,
//200x200
ready: () => {
const size = 200
const container = this.$el.querySelector('.avatar-cropper')
const top = (500 - size) / 2
const left = (container.offsetWidth - size) / 2
this.cropper.setCropBoxData({width: size, height: size, top, left})
} }
reader.readAsArrayBuffer(file) }
)
})
}, },
chooseImage() {
this.$refs.input.click()
},
confirm() { confirm() {
if (!this.img) return elError('请先上传图片') if (!this.img) return elError('请先上传图片')
if (this.loading) return if (this.loading) return
this.loading = true this.loading = true
this.$refs.cropper.getCropBlob(data => {
upload(new Blob([data]), this.name) this.cropper
.then(({data}) => updateAvatar.request(data.data)) .getCroppedCanvas()
.toBlob(
data => {
upload(data, this.name)
.then(({key}) => updateAvatar.request(key))
.then(({data, msg}) => { .then(({data, msg}) => {
this.$store.commit('user/avatar', autoCompleteUrl(data)) this.$store.commit('user/avatar', autoCompleteUrl(data))
this.$store.dispatch('user/refresh') this.$store.dispatch('user/refresh')
elSuccess(msg) elSuccess(msg)
this.closeDialog()
}) })
.finally(() => this.cancel()) .finally(() => this.loading = false)
}) },
this.type
)
}
}, },
cancel() { beforeDestroy() {
this.closeDialog()
this.clear() this.clear()
} }
} }
}
</script> </script>
<style lang="scss"> <style lang="scss">
.avatar-cropper { .avatar-cropper {
height: 500px; height: 500px;
width: 100%; width: 100%;
border: 1px solid #ebebeb;
.cropper-crop-box { &-bg {
border-radius: 50%; height: 100%;
overflow: hidden; width: 100%;
cursor: pointer;
}
> img {
display: none;
height: 100%;
width: 100%;
} }
> input[type=file] { > input[type=file] {
display: none; display: none;
} }
.cropper-view-box {
border-radius: 50%;
box-sizing: border-box;
border: 1px solid rgba(51, 153, 255, .75);
outline: unset;
}
.cropper-face {
border-radius: 50%;
}
} }
</style> </style>

Loading…
Cancel
Save