elementUI上传组件改造--扫码上传
1、需求
接到客户方的需求:web端如果要上传图片,通常得,
1、手机拍照
2、拷贝到电脑
3、电脑再点击上传(手机的安全性,不熟悉的话,十分麻烦)
客户需要直接在手机上直接上传到系统,十分合理,非常有价值的功能
2、分析
1、跨终端(打通pc和移动端的壁垒)
2、不影响原有功能(不改动原来代码,否则,可能会导致业务逻辑改变,会需要测试同事重新测试,需避免)
3、手机上传后,怎么pc端如何监听,并做反馈操作(主动触发即可)
3、实现
1、跨终端
依照现有的JWT,可以通过url携带token的方式,携带token到h5端,那么,这个时候就可以上传图片了
2、pc端生成二维码
qrcode.js 可以生成二维码,把扫码上传的项目部署了,pc端用该地址拼接token,即可生成携带token的二维码了
3、不影响原有功能
这个功能需要对原有上传组件的二次封装,我们使用的是elementUI,采用的是上传组件,一如我上一篇文章所说,需要进行二次封装,由于是组件,在组件上,还能进行各种自定义的封装,例如动态加一个class,例如,添加一个原生click事件,开发完全自主,所以,得用上render,利用完全js实现无痛轻松过度
代码:
<script> import { Upload } from 'element-ui' import QRCode from 'qrcode' import { getFileUploadCode, getFileUrlByCode } from '@/const/fileLibraryApi.js' import { hasIn } from 'lodash' export default { name: 'MyUpload', components: { mUpload: Upload }, data () { return { qrcodeImg: '', backVisible: false, qrcodeLoading: false, code: '' } }, methods: { qrcodeBtn () { this.backVisible = true this.qrcodeLoading = true let originUrl = window.location.origin.includes('.com') ? window.location.origin : 'https://xxx.com' this.$axios({ url: getFileUploadCode, method: 'post' }).then(res => { let code = hasIn(res, ['data', 'payload']) ? res.data.payload : '' if (!code) { this.$message({ type: 'warning', message: '获取状态码失败,请联系管理员!' }) return } this.code = code QRCode.toDataURL(`${originUrl}/xx-h5/#/file?token=${this.$store.state.token}&code=${code}`) .then(url => { this.qrcodeImg = url this.qrcodeLoading = false }) .catch(() => { this.$message({ type: 'error', message: '生成二维码失败,建议使用本地上传!' }) }) }) }, // 取消提示 cancleConfirm () { this.$confirm('还未检测到通过二维码上传的文件,是否取消二维码上传?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.backVisible = false }).catch(() => { this.qrcodeLoading = false }) }, backClick () { this.qrcodeLoading = true this.$axios({ url: getFileUrlByCode, method: 'post', data: { code: this.code } }).then(res => { let imgUrl = hasIn(res, ['data', 'payload']) ? res.data.payload : '' if (!imgUrl) { this.cancleConfirm() return } let mProps = this.$attrs['m-props'] mProps.urlObj[mProps.urlStr] = imgUrl this.backVisible = false }).catch(() => { this.backVisible = false this.$message({ type: 'warning', message: '获取上传图片失败,建议使用本地上传!' }) }) } }, render (h) { const attrsMethods = slots => { let values = Object.values(slots) let sList = [] values.forEach(vnodes => { sList.push(vnodes) }) return sList } const qrcodeShow = (h) => { return this.backVisible ? h( 'div', { class: { 'back-mask': true }, on: { 'click': this.backClick } }, this.qrcodeImg ? [h( 'el-image', { 'class': { 'back-qrcode-img': true }, directives: [{ name: 'loading', value: this.qrcodeLoading }], props: { fit: 'fitType', src: this.qrcodeImg } } )] : [] ) : [] } return h('div', { class: { 'qrcode_upload_box': true } }, [ h( 'm-upload', { props: this.$attrs, on: this.$listeners, ref: 'mUpload' }, attrsMethods(this.$slots) ), h('el-button', { class: { 'qrcode_box': true }, props: { icon: 'el-icon-mobile-phone', circle: true, disabled: this.$attrs.disabled }, attrs: { title: '手机上传二维码' }, on: { click: this.qrcodeBtn } }), qrcodeShow(h) ]) } } </script> <style lang="less" scoped> .qrcode_upload_box { position: relative; width: 100%; height: 100%; .qrcode_box { position: absolute; top: 0; right: 0; transform: translate(50%, 50%); z-index: 99; } .back-mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.7); z-index: 100; display: flex; align-items: center; justify-content: center; .back-qrcode-img { width: 250px; height: 250px; } } } </style>
以上是完整功能代码,包括了:如何判断是哪个控件的上传?是否重复上传了?上传后怎么在pc端渲染出来?前两个问题需要后端提供支持,最后一个问题,实际上利用了内存地址的方式