
- <div class="form-box-item">
- <div class="form-box-item-label">交易盈利证明div>
- <el-upload
- v-if="!ImageProve"
- class="upload-box"
- ref="uploadRef"
- drag
- multiple
- action=""
- :limit="1"
- :auto-upload="false"
- :http-request="uploadBpmn"
- :before-upload="(file) => beforeUpload(file)"
- :on-change="handleChange"
- :on-error="handError"
- >
- <img src="@/assets/images/futures/upload.png" alt="" />
- <div class="el-upload__text">
- <div class="upload-green-text">上传文件div>
- <div class="upload-text">或拖拽放入div>
- div>
- el-upload>
- <img v-else style="width: 150px" :src="ImageProve" />
- div>
- const uploadRef = ref(null);
-
- const fileType = ref({
- limitSize: 2,
- type: 'png'
- });
-
- const beforeUpload = (file) => {
- console.log('beforeUpload', file);
- // 上传文件之前钩子
- const type = file.name.split('.')[file.name.split('.').length - 1];
- console.log(type, '文件格式!');
-
- if (file && file.size / 1024 / 1024 > fileType.value.limitSize) {
- ElMessage.error(`文件大小不能超过${fileType.value.limitSize}`);
- return false;
- }
- if (file && !fileType.value.type.indexOf(file.type) == -1) {
- ElMessage.error(`只能上传${fileType.value.type}类型的文件`);
- return false;
- }
- };
- const uploadBpmn = (param) => {
- console.log('uploadBpmn', param);
- // const formData = new FormData();
- // formData.append('file', param.file);
- // console.log(formData.get('file'), param, 888);
- };
-
- const handleChange = (response, file, fileList) => {
- console.log('handleChange', response, file, fileList);
- // getProfileAvatarUploadParam(response);
- // console.log(uploadRef.value, 99);
- uploadRef.value.clearFiles(); //清除文件对象
- // uploadRef.value.submit() //提交 .clearFiles()清除
- };
-
- const handError = (error, file, fileList) => {
- console.log('handError', error, file, fileList);
- };
-
- // 获取头像上传参数
- const getProfileAvatarUploadParam = async (file) => {
- try {
- let params = {
- contentType: file.raw.type || 'image/png'
- };
- const {
- data: { data }
- } = await profileAvatarUploadParam(params);
- console.log('getProfileAvatarUploadParam', data);
- uploadImage(data, file);
- } catch (error) {
- console.log('getProfileAvatarUploadParam', error);
- }
- };
-
- const ImageProve = ref(null);
-
- // 上传图片
- const uploadImage = async (xhrData, file) => {
- console.log('uploadImage', xhrData, file);
- try {
- const formData = new FormData();
- for (const key in xhrData.param) {
- const value = xhrData.param[key];
- formData.append(key, value);
- }
- formData.append('file', file.raw);
- // console.log(xhrData.param, formData.get('file'), 9898);
- let config = {
- method: 'post',
- // maxBodyLength: Infinity,
- url: xhrData.uploadUrl,
- data: formData,
- headers: {
- 'Content-Type': 'multipart/form-data'
- }
- };
- const res = await axios.request(config);
- ImageProve.value = xhrData.accessUrl;
- console.log('uploadImage', res);
- } catch (error) {
- console.log('uploadImage', error);
- }
- };
在Vue3中,我们可以使用element-plus提供的el-upload组件进行图片上传。但是有时候我们需要根据具体业务需求对该组件进行二次封装,以适应项目中的具体场景。下面给出一个基于element-plus的el-upload组件的二次封装,实现图片上传和图片预览功能。
在Vue3项目中,我们可以使用npm或yarn来安装element-plus组件库。
- // 使用npm安装element-plus
- npm install element-plus --save
-
- // 使用yarn安装element-plus
- yarn add element-plus
在封装图片上传组件时,我们可以将el-upload组件进行二次封装,以方便在项目中的使用。具体封装代码如下:
- <el-upload
- :action="actionUrl"
- :show-file-list="showFileList"
- :multiple="multiple"
- :limit="limit"
- :on-exceed="handleExceed"
- :on-success="handleSuccess"
- :before-remove="beforeRemove"
- :on-remove="handleRemove"
- :on-preview="handlePreview"
- :file-list="fileList">
- <template #tip>
- <div class="el-upload__tip">{{ tip }}div>
- template>
- <template #default>
- <i class="el-icon-plus avatar-uploader-icon">i>
- template>
- el-upload>
-
- <script>
- export default {
- name: 'AvatarUploader',
- props: {
- actionUrl: {
- type: String,
- default: ''
- },
- showFileList: {
- type: Boolean,
- default: true
- },
- multiple: {
- type: Boolean,
- default: false
- },
- limit: {
- type: Number,
- default: 1
- },
- tip: {
- type: String,
- default: '只能上传jpg/png文件,且不超过2M'
- },
- fileList: {
- type: Array,
- default() {
- return [];
- }
- }
- },
- methods: {
- handleExceed(files, fileList) {
- this.$message.warning(`只能上传${this.limit}个文件`);
- },
- handleSuccess(response, file, fileList) {
- console.log(response, file, fileList);
- this.$emit('success', response, file, fileList);
- },
- beforeRemove(file, fileList) {
- return this.$confirm(`确定移除 ${file.name}?`);
- },
- handleRemove(file, fileList) {
- console.log(file, fileList);
- this.$emit('remove', file, fileList);
- },
- handlePreview(file) {
- window.open(file.url, '_blank');
- }
- }
- };
- script>
-
- <style scoped>
- .avatar-uploader {
- display: inline-block;
- width: 100px;
- height: 100px;
- border-radius: 50%;
- background-size: cover;
- background-position: center center;
- overflow: hidden;
- position: relative;
- }
- .avatar-uploader input {
- display: none;
- }
- .avatar-uploader-icon {
- display: block;
- width: 100%;
- height: 100%;
- line-height: 100px;
- text-align: center;
- font-size: 28px;
- color: #999;
- background-color: #fff;
- cursor: pointer;
- }
- .el-upload__tip {
- font-size: 12px;
- color: #999;
- margin-top: 10px;
- text-align: center;
- }
- style>
在该封装组件中,我们定义了一些props属性,包括文件上传地址(actionUrl)、是否显示文件列表(showFileList)、是否支持多选(multiple)、最大上传文件个数(limit)、上传提示内容(tip)、文件列表(fileList)等。我们还定义了一些方法,包括文件数量超限(handleExceed)、文件上传成功(handleSuccess)、文件删除前(beforeRemove)、文件删除成功(handleRemove)、文件预览(handlePreview)等。在该封装组件中,我们使用了element-plus提供的el-upload组件,并在其基础上进行了二次封装。
在项目中使用我们封装好的图片上传组件非常简单,只需要在具体页面中引入该组件并传递相应的props属性即可。具体代码如下:
- <div class="upload-wrapper">
- <avatar-uploader
- :action-url="uploadUrl"
- :show-file-list="true"
- :multiple="false"
- :limit="1"
- :tip="uploadTip"
- :file-list="fileList"
- @success="handleSuccess"
- @remove="handleRemove">
- avatar-uploader>
- div>
-
- <script>
- import AvatarUploader from '@/components/AvatarUploader.vue';
-
- export default {
- name: 'ImageUploadPage',
- components: {
- AvatarUploader
- },
- data() {
- return {
- uploadUrl: '',
- uploadTip: '只能上传jpg/png文件,且不超过2M',
- fileList: []
- };
- },
- methods: {
- handleSuccess(response, file, fileList) {
- console.log(response, file, fileList);
- },
- handleRemove(file, fileList) {
- console.log(file, fileList);
- }
- }
- };
- script>
-
- <style scoped>
- .upload-wrapper {
- width: 500px;
- margin: 0 auto;
- }
- style>
在上述代码中,我们在ImageUploadPage页面中引入了我们封装好的AvatarUploader组件,并传递了相应的props属性。在实际使用中,我们可以根据具体业务需求进行修改和调整。
Vue3中可以通过对element-plus的el-upload进行二次封装来实现图片上传组件的封装。下面是一份简单的示例:
1、安装element-plus:
npm install element-plus --save
2、创建一个Upload.vue组件,并引入element-plus和相关样式:
- <template>
- <el-upload
- class="upload-demo"
- drag
- :headers="headers"
- :action="action"
- :multiple="multiple"
- :data="data"
- :before-upload="beforeUpload"
- :on-success="onSuccess"
- :on-error="onError"
- :on-exceed="handleExceed"
- :limit="limit"
- :show-file-list="showFileList"
- :file-list="fileList">
- <slot name="uploadButton">slot>
- <slot name="tip">slot>
- el-upload>
- template>
-
- <script>
- import { ref } from 'vue'
- import 'element-plus/packages/theme-chalk/src/base.scss'
- import 'element-plus/packages/theme-chalk/src/upload.scss'
- import {
- ElUpload,
- ElButton,
- ElPopover,
- } from 'element-plus'
- export default {
- components: {
- ElUpload,
- ElButton,
- ElPopover,
- },
- props: {
- action: {
- type: String,
- required: true,
- },
- headers: {
- type: Object,
- default: () => ({}),
- },
- multiple: {
- type: Boolean,
- default: false,
- },
- data: {
- type: Object,
- default: () => ({}),
- },
- limit: {
- type: Number,
- default: 0,
- },
- showFileList: {
- type: Boolean,
- default: true,
- },
- },
- emits: ['success', 'error'],
- setup(props, { emit }) {
- const fileList = ref([])
- const beforeUpload = (file) => {
- const isJPG = file.type === 'image/jpeg'
- const isGIF = file.type === 'image/gif'
- const isPNG = file.type === 'image/png'
- const isLt2M = file.size / 1024 / 1024 < 2
-
- if (!isJPG && !isGIF && !isPNG) {
- this.$message.error('上传图片只能是 JPG/GIF/PNG 格式!')
- return false
- }
- if (!isLt2M) {
- this.$message.error('上传图片大小不能超过 2MB!')
- return false
- }
- return true
- }
- const handleExceed = (files, fileList) => {
- this.$message.warning(`当前限制选择 ${props.limit} 张图片,本次选择了 ${files.length} 张,共选择了 ${files.length + fileList.length} 张。`)
- }
- const onSuccess = (response, file, fileList) => {
- emit('success', response, file, fileList)
- }
- const onError = (err, file, fileList) => {
- emit('error', err, file, fileList)
- }
- return {
- fileList,
- beforeUpload,
- handleExceed,
- onSuccess,
- onError,
- }
- },
- }
- script>
-
- <style scoped>
- .upload-demo {
- margin-top: 10px;
- display: flex;
- flex-wrap: wrap;
- justify-content: flex-start;
- align-items: center;
- }
-
- .upload-demo .el-upload {
- margin-right: 15px;
- margin-bottom: 15px;
- }
-
- .upload-demo .el-upload__tip {
- margin: 0;
- }
-
- .upload-demo .el-upload-list {
- margin: 0;
- }
- style>
3、在父级组件中使用Upload.vue组件:
- <template>
- <div class="page">
- <upload
- :action="uploadUrl"
- :show-file-list="false"
- :limit="limit"
- @success="handleSuccess"
- @error="handleError"
- >
- <el-button size="small" type="primary">上传文件el-button>
- <el-popover
- slot="tip"
- placement="top"
- :width="tipWidth"
- trigger="hover"
- >
- <el-image
- style="width: 100%;"
- :src="tipImage"
- @error="handleTipImageError"
- />
- el-popover>
- upload>
- <el-upload-list :list-type="listType" :items="fileList" />
- div>
- template>
-
- <script>
- import Upload from '@/components/Upload.vue'
- import { ref } from 'vue'
- import { ElUploadList, ElButton, ElImage } from 'element-plus'
- import 'element-plus/packages/theme-chalk/src/base.scss'
- import 'element-plus/packages/theme-chalk/src/upload.scss'
-
- export default {
- components: {
- Upload,
- ElUploadList,
- ElButton,
- ElImage,
- },
- setup() {
- const fileList = ref([])
- const limit = 5
- const listType = 'picture-card'
- const uploadUrl = 'https://jsonplaceholder.typicode.com/posts/'
-
- const handleSuccess = (response, file, fileList) => {
- fileList.push({
- name: file.name,
- url: URL.createObjectURL(file.raw),
- })
- }
- const handleError = (err, file, fileList) => {
- console.error(err)
- }
-
- return {
- fileList,
- limit,
- listType,
- uploadUrl,
- handleSuccess,
- handleError,
- }
- },
- }
- script>
-
- <style scoped>
- .page {
- max-width: 640px;
- margin: 0 auto;
- }
- style>
通过以上代码示例可以看出,在Upload.vue组件中,我们可以通过props来接收父组件传递的参数,比如上传地址(action)、上传时携带的参数(data)、上传的文件头信息(headers)等等。在父组件中,我们通过使用Upload.vue组件,并将需要上传的参数作为props传递给上传组件,同时也可以在Upload.vue组件中使用自定义事件来向父组件派发成功或错误的事件,比如上传成功事件(success)和上传错误事件(error)等等。在父组件中,我们可以通过设置listType属性来控制文件列表的显示方式,比如图片卡片显示方式(picture-card)或文件列表方式(text)等等。
Vue3中图片上传组件的二次封装可以使用Element Plus中的el-upload组件。el-upload组件是一个通用的上传组件,支持多文件上传、拖拽上传、图片裁剪等功能。以下是一个基于Element Plus的el-upload组件的二次封装实例:
- <div>
- <el-upload
- class="upload-demo"
- ref="upload"
- :action="actionUrl"
- :headers="headers"
- :data="formData"
- :multiple="multiple"
- :auto-upload="autoUpload"
- :limit="limit"
- :on-exceed="handleExceed"
- :on-change="handleChange"
- :file-list="fileList"
- list-type="picture"
- :show-file-list="false"
- >
- <el-button size="small" type="primary">点击上传el-button>
- <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过2MBdiv>
- el-upload>
- <el-dialog :visible.sync="dialogVisible" width="50%">
- <img :src="imgUrl" style="width: 100%">
- el-dialog>
- div>
- template>
-
- <script>
- import { ref } from 'vue'
-
- export default {
- name: 'ImgUpload',
- props: {
- actionUrl: {
- type: String,
- required: true
- },
- headers: {
- type: Object,
- default: () => ({})
- },
- formData: {
- type: Object,
- default: () => ({})
- },
- multiple: {
- type: Boolean,
- default: false
- },
- autoUpload: {
- type: Boolean,
- default: true
- },
- limit: {
- type: Number,
- default: 1
- }
- },
- setup(props) {
- const fileList = ref([]);
- const dialogVisible = ref(false);
- const imgUrl = ref('');
-
- const handleChange = ({ file, fileList }) => {
- if (file.response) {
- if (file.response.code !== 0) {
- this.$message.error(file.response.message);
- } else {
- imgUrl.value = file.response.data;
- dialogVisible.value = true;
- }
- }
- fileList.value = fileList.slice(-props.limit);
- };
-
- const handleExceed = (files, fileList) => {
- this.$message.warning(`只能上传${props.limit}个文件`);
- };
-
- return {
- fileList,
- dialogVisible,
- imgUrl,
- handleChange,
- handleExceed
- };
- }
- }
- script>
在img-upload组件中,我们用了Element Plus的el-upload组件,并且通过props来传递一些参数,包括上传路径(actionUrl)、请求头(headers)、上传数据(formData)、是否允许多个文件上传(multiple)、是否自动上传(autoUpload)和文件数量限制(limit)。在setup函数中,我们通过useRef来定义变量fileList、dialogVisible和imgUrl,并且定义handleChange和handleExceed两个方法,用于处理上传和文件数量超过限制的情况。在模板中,我们用el-dialog组件来显示上传的图片,并且为el-upload组件添加了一个提示消息。
这是一个简单的el-upload组件的二次封装实例,可以根据项目需求进行适当修改。