Vue中圖片上傳組件封裝-antd的a-upload二次封裝的實例
圖片上傳組件封裝-antd的a-upload二次封裝

api
const publicApi = {
UploadImage: '/common/uploadImage',
DeleteImage: '/common/deleteImage',
}
/**
* 上傳圖片
* @param {*} parameter
* @returns
*/
export function UploadImage(parameter) {
return request({
url: publicApi.UploadImage,
method: 'post',
data: parameter
})
}
/**
* 刪除圖片 :name
* @param {*} parameter
* @returns
*/
export function DeleteImage(parameter) {
return request({
url: `${publicApi.DeleteImage}/${parameter}`,
method: 'delete'
// params: parameter
})
}組件封裝
<template>
<div class="upbase">
<!-- 進度條-->
<div v-show="progressVisible" class="progress-container">
<div class="progress-bar"></div>
</div>
<a-upload
v-if="!uploadType"
:beforeUpload="beforeImageUpload"
list-type="picture-card"
:file-list="imageList"
:multiple="multiple"
:disabled="disabled"
@change="handleImageChange"
@preview="handlePreview"
:custom-request="customRequest"
>
<div v-if="imageList.length < limitNum && !disabled">
<a-icon type="plus" />
<div class="ant-upload-text">上傳</div>
</div>
</a-upload>
<a-upload
v-else
name="file"
:file-list="imageList"
:beforeUpload="beforeImageUpload"
:multiple="multiple"
:disabled="disabled"
:custom-request="customRequest"
@change="handleImageChange"
>
<!-- list-type="picture" -->
<div v-if="imageList.length < limitNum && !disabled">
<a-button> <a-icon type="upload" /> 上傳 </a-button>
</div>
</a-upload>
<!-- 圖片預(yù)覽 -->
<a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
<img alt="example" style="width: 100%" :src="previewImage" />
</a-modal>
</div>
</template>
<script>
import { UploadImage, DeleteImage } from '@/api/public'
function getBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = () => resolve(reader.result)
reader.onerror = (error) => reject(error)
})
}
function getName(url) {
const list = url.split('/')
return list[list.length - 1].split('.')[0]
}
export default {
name: 'UpBase64',
props: {
defaultImageList: {
type: Array,
default: function () {
return []
},
required: true,
},
// 組件展示樣式
uploadType: {
type: Boolean,
default: false,
required: false,
},
// 文件類型列表
fileTypeList: {
type: Array,
default: function () {
return []
},
required: false,
},
// 容量大小
limitSize: {
type: Number,
default: 2,
required: false,
},
// 個數(shù)
limitNum: {
type: Number,
default: 20,
required: false,
},
// 是否支持多選
multiple: {
type: Boolean,
default: false,
required: false,
},
// 是否禁用
disabled: {
type: Boolean,
default: false,
required: false,
},
dwidth: {
type: Number,
default: 0,
require: false,
},
dheight: {
type: Number,
default: 0,
require: false,
},
},
data() {
return {
previewVisible: false,
progressVisible: false,
progressValue: 10,
previewImage: '',
imageList: [],
}
},
watch: {
defaultImageList(newVal) {
this.imageList = this.handleData(newVal)
},
},
created() {
this.imageList = this.handleData(this.defaultImageList)
},
methods: {
// ---------------------------------------------img--start
// 上傳格式限制
beforeImageUpload(file) {
return new Promise((resolve, reject) => {
if (this.fileTypeList.length != 0) {
const index = this.fileTypeList.indexOf(file.type)
if (index <= -1) {
this.$message.error(`您只能上傳${this.fileTypeList}文件`)
return reject(new Error(`您只能上傳${this.fileTypeList}文件,不能傳${file.type}文件`))
}
}
const limitSize = file.size / 1024 / 1024 < this.limitSize
if (!limitSize) {
this.$message.error(`文件大小不能大于${this.limitSize}MB`)
return reject(new Error(`文件大小不能大于${this.limitSize}MB`))
}
const checkSize = this.checkImageWH(file, this.dwidth, this.dheight)
return Promise.resolve(checkSize)
.then(() => resolve())
.catch((e) => {
reject(e)
})
})
},
checkImageWH(file, width, height) {
// 參數(shù)分別是上傳的file,想要限制的寬,想要限制的高
const that = this
return new Promise(function (resolve, reject) {
let filereader = new FileReader()
filereader.onload = (e) => {
let src = e.target.result
const image = new Image()
image.onload = function () {
if ((width && this.width !== width) || (height && this.height !== height)) {
// 上傳圖片的寬高與傳遞過來的限制寬高作比較,超過限制則調(diào)用失敗回調(diào)
const message = `圖片寬高不滿足,需要:寬 ${width || '不限制'},高 ${height || '不限制'}\n,當(dāng)前圖片寬:${
this.width
},高:${this.height}`
that.$message.error(message)
reject(new Error(message))
} else {
resolve({ width: this.width, height: this.height })
}
}
image.onerror = reject
image.src = src
}
filereader.readAsDataURL(file)
})
},
async handlePreview(file) {
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj)
}
this.previewImage = file.url || file.preview
this.previewVisible = true
},
handleCancel() {
this.previewVisible = false
},
// 自定義上傳邏輯
customRequest({ action, file, onSuccess, onError, onProgress }) {
this.progressVisible = true
new Promise((resolve) => {
const fileReader = new FileReader()
// 轉(zhuǎn)化為base64
fileReader.readAsDataURL(file)
fileReader.onload = async () => {
let index = {
uid: this.genId(5),
name: file.name,
status: 'done',
url: fileReader.result,
}
let params = {
name: index.uid,
data: index.url,
}
try {
let res = await UploadImage(params)
index.url = res.result.url
if (res.status == 1) {
setTimeout(() => {
this.imageList = [...this.imageList.filter((item) => item.status === 'done'), index]
this.$message.success('文件上傳成功!')
this.progressVisible = false
this.handleChange()
resolve(fileReader.result)
}, 2000)
} else {
this.imageList = [...this.imageList.filter((item) => item.status === 'done')]
this.$message.success(res.msg)
this.handleChange()
resolve(fileReader.result)
}
} catch (error) {
console.log('upimg:', error)
} finally {
}
}
})
},
// 處理事件
async handleImageChange(info) {
try {
// 刪除圖片
let res = await DeleteImage(getName(info.file.url))
console.log(res, 89)
if (res.status == 1) {
this.$message.success('刪除成功!')
} else {
this.$message.error('刪除失?。?)
}
} catch (error) {
// console.log('delimg:', error)
} finally {
let fileList = [...info.fileList]
this.imageList = fileList
this.handleChange()
}
},
handleChange() {
let index = this.imageList
.filter((item) => item.url)
.map((item) => {
return item.url
})
// if (index?.length <= 0) return
this.$emit('change', index ? index : [])
},
genId(length) {
return Number(Math.random().toString().substr(3, length) + Date.now()).toString(36)
},
handleData(list) {
return list.map((item) => {
let index = this.genId(5)
return {
uid: index,
name: index,
status: 'done',
url: item,
}
})
},
// ---------------------------------------------img--end
},
}
</script>
<style lang="less" scoped>
.ant-upload-select-picture-card i {
font-size: 32px;
color: #999;
}
.ant-upload-select-picture-card .ant-upload-text {
margin-top: 8px;
color: #666;
}
</style>
<style>
.progress-container {
width: 100px;
height: 7px;
background-color: #ffffff;
border-radius: 5px;
}
.progress-bar {
height: 100%;
border-radius: 5px;
animation-fill-mode: forwards;
animation-name: progressBar;
animation-iteration-count: infinite;
background-color: #44cef6;
animation-duration: 2s;
animation-iteration-count: 1;
}
@keyframes progressBar {
0% {
width: 0%;
}
100% {
width: 100%;
}
}
</style>使用
<template>
<page-header-wrapper>
<div class="khdztps">
<div class="container">
<div class="left">
<div class="wrap">
<div class="title">
<h2>客戶端底圖上傳</h2>
</div>
<span class="tips">*上傳格式為“.jpg 和.png“,大小不得超過1M,(375*665)</span>
<b-upload-image-base64
ref="bUploadImageBase641"
:limitNum="1"
@change="imageChange($event, 'inviteBgImageList')"
:defaultImageList="inviteBgImageList"
:dwidth="375"
:dheight="665"
/>
</div>
<div class="wrap">
<div class="title">
<h2>客戶端ICON替換</h2>
</div>
<span class="tips">*上傳格式只能為“.png”,大小不得超過300k,(24*24)x3</span>
<div class="icon">
<div class="wxz">
<span class="title">未選中</span>
<div class="imgBox">
<b-upload-image-base64
ref="bUploadImageBase642"
:limitNum="1"
@change="imageChange($event, 'inviteHomeImageList')"
:defaultImageList="inviteHomeImageList"
:dwidth="24 * 3"
:dheight="24 * 3"
/>
</div>
</div>
</div>
</div>
</div>
</div>
<a-button type="primary" @click="saveSubmit">保存并預(yù)覽</a-button>
</div>
</page-header-wrapper>
</template>
<script>
import { commitCustomConfigure, queryCustomConfigure } from '@/api/feedback'
import bUploadImageBase64 from '@/components/Plug/BUploadImageBase64.vue'
export default {
name: 'Khdztps',
components: {
bUploadImageBase64,
},
data() {
return {
inviteBgImageList: [],
inviteHomeImageList: [],
dataList: {
BGUrl: '',
HomeUrl: '',
},
}
},
created() {},
mounted() {
this.queryCustomConfigure()
},
methods: {
saveSubmit() {
this.commitCustomConfigure()
},
// 保存
async commitCustomConfigure() {
try {
let res = await commitCustomConfigure(this.dataList)
console.log(res, 89)
if (res.status == 1) {
this.$message.success('設(shè)置成功!')
} else {
this.$message.error(res.msg)
}
} catch (error) {
console.log('sub:', error)
}
},
// 獲取 - 數(shù)據(jù)回填
async queryCustomConfigure() {
try {
let res = await queryCustomConfigure()
console.log(res, 89)
if (res.status == 1) {
// this.$message.success('成功!')
this.dataList = res.result
if (res.result.BGUrl) {
this.inviteBgImageList.push(res.result.BGUrl)
}
if (res.result.HomeUrl) {
this.inviteHomeImageList.push(res.result.HomeUrl)
}
} else {
this.$message.error(res.msg)
}
} catch (error) {
console.log('sub:', error)
}
},
// 圖片上傳成功賦值
imageChange(e, key) {
console.log(e, key)
switch (key) {
// 圖片
case 'inviteBgImageList':
this.dataList.BGUrl = e[0] || ''
break
case 'inviteHomeImageList':
this.dataList.Unselect.Home = e[0] || ''
break
default:
break
}
},
},
destroyed() {},
activated() {},
deactivated() {},
}
</script>
優(yōu)化
原本 :defaultImageList="inviteBgImageList" ==>['圖片鏈接']
現(xiàn)在 :defaultImageList="Array(form.BGUrl)" ==>['圖片鏈接']
原本的寫法需要提前定義好一個空數(shù)組,才能將數(shù)據(jù)回填顯示出圖片
現(xiàn)在的寫法是直接使用form中的字符串轉(zhuǎn)換成一個數(shù)組回填顯示圖片
二者方式均可使用,看使用方式
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue 級聯(lián)下拉框的設(shè)計與實現(xiàn)
在前端開發(fā)中,級聯(lián)選擇框是經(jīng)常用到的,這樣不僅可以增加用戶輸入的友好性,還能減少前后端交互的數(shù)據(jù)量。本文就介紹一下使用Vue實現(xiàn)級聯(lián)下拉框,感興趣的可以了解一下2021-07-07
VueJs單頁應(yīng)用實現(xiàn)微信網(wǎng)頁授權(quán)及微信分享功能示例
本篇文章主要介紹了VueJs單頁應(yīng)用實現(xiàn)微信網(wǎng)頁授權(quán)及微信分享功能示例,具有一定的參考價值,有興趣的可以了解一下2017-07-07
Vue3中實現(xiàn)拖拽和縮放自定義看板 vue-grid-layout的方法
這篇文章主要介紹了Vue3中實現(xiàn)拖拽和縮放自定義看板 vue-grid-layout的方法,本文結(jié)合實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03

