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端渲染出來?前兩個問題需要后端提供支持,最后一個問題,實際上利用了內存地址的方式