parent
6bd0df2cb6
commit
92b34eb5b7
|
|
@ -9,6 +9,13 @@ export default {
|
|||
return await http.post(this.url, data, config);
|
||||
}
|
||||
},
|
||||
uploadFile: {
|
||||
url: `${config.API_URL}/uploadFile`,
|
||||
name: "附件上传",
|
||||
post: async function(data, config={}){
|
||||
return await http.post(this.url, data, config);
|
||||
}
|
||||
},
|
||||
file: {
|
||||
menu: {
|
||||
url: `${config.API_URL}/file/menu`,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,149 @@
|
|||
<template>
|
||||
<div class="sc-upload-file">
|
||||
<el-upload :disabled="disabled" :auto-upload="autoUpload" :action="action" :http-request="request" :file-list="defaultFileList" :show-file-list="showFileList" :drag="drag" :accept="accept" :multiple="multiple" :limit="limit" :before-upload="before" :on-success="success" :on-error="error" :on-preview="handlePreview" :on-exceed="handleExceed">
|
||||
<slot>
|
||||
<el-button type="primary" :disabled="disabled">Click to upload</el-button>
|
||||
</slot>
|
||||
<template #tip>
|
||||
<div v-if="tip" class="el-upload__tip">{{tip}}</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<span style="display:none!important"><el-input v-model="value"></el-input></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from "@/config/upload"
|
||||
|
||||
export default {
|
||||
props: {
|
||||
modelValue: { type: String, default: "" },
|
||||
tip: { type: String, default: "" },
|
||||
action: { type: String, default: "" },
|
||||
apiObj: { type: Object, default: () => {} },
|
||||
accept: { type: String, default: "" },
|
||||
maxSize: { type: Number, default: config.maxSizeFile },
|
||||
limit: { type: Number, default: 0 },
|
||||
autoUpload: { type: Boolean, default: true },
|
||||
showFileList: { type: Boolean, default: true },
|
||||
drag: { type: Boolean, default: false },
|
||||
multiple: { type: Boolean, default: true },
|
||||
disabled: { type: Boolean, default: false },
|
||||
onSuccess: { type: Function, default: () => { return true } }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: "",
|
||||
defaultFileList: []
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
modelValue(val){
|
||||
if (val != this.toStr(this.defaultFileList)) {
|
||||
this.defaultFileList = this.toArr(val)
|
||||
this.value = val
|
||||
}
|
||||
},
|
||||
defaultFileList: {
|
||||
handler(val){
|
||||
this.$emit('update:modelValue', this.toStr(val))
|
||||
this.value = this.toStr(val)
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.value = this.modelValue
|
||||
this.defaultFileList = this.toArr(this.modelValue)
|
||||
},
|
||||
methods: {
|
||||
//默认值转换为数组
|
||||
toArr(str){
|
||||
var _arr = [];
|
||||
var arr = str.split(",");
|
||||
arr.forEach(item => {
|
||||
if(item){
|
||||
var urlArr = item.split('/');
|
||||
var fileName = urlArr[urlArr.length - 1]
|
||||
_arr.push({
|
||||
name: fileName,
|
||||
url: item
|
||||
})
|
||||
}
|
||||
})
|
||||
return _arr;
|
||||
},
|
||||
//数组转换为原始值
|
||||
toStr(arr){
|
||||
return arr.map(v => v.url).join(",")
|
||||
},
|
||||
before(file){
|
||||
const maxSize = file.size / 1024 / 1024 < this.maxSize;
|
||||
if (!maxSize) {
|
||||
this.$message.warning(`上传文件大小不能超过 ${this.maxSize}MB!`);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
success(res, file){
|
||||
var os = this.onSuccess(res, file)
|
||||
if(os!=undefined && os==false){
|
||||
return false
|
||||
}
|
||||
var response = config.parseData(res)
|
||||
file.name = response.fileName
|
||||
file.url = response.src
|
||||
},
|
||||
error(err){
|
||||
this.$notify.error({
|
||||
title: '上传文件未成功',
|
||||
message: err
|
||||
})
|
||||
},
|
||||
beforeRemove(uploadFile){
|
||||
return this.$confirm(`是否移除 ${uploadFile.name} ?`, '提示', {
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
return true
|
||||
}).catch(() => {
|
||||
return false
|
||||
})
|
||||
},
|
||||
handleExceed(){
|
||||
this.$message.warning(`当前设置最多上传 ${this.limit} 个文件,请移除后上传!`)
|
||||
},
|
||||
handlePreview(uploadFile){
|
||||
window.open(uploadFile.url)
|
||||
},
|
||||
request(param){
|
||||
var apiObj = config.apiObjFile;
|
||||
if(this.apiObj){
|
||||
apiObj = this.apiObj;
|
||||
}
|
||||
const data = new FormData();
|
||||
var file = param.file
|
||||
data.append("file", file);
|
||||
apiObj.post(data, {
|
||||
onUploadProgress: e => {
|
||||
const complete = parseInt(((e.loaded / e.total) * 100) | 0, 10)
|
||||
param.onProgress({percent: complete})
|
||||
}
|
||||
}).then(res => {
|
||||
var response = config.parseData(res);
|
||||
if(response.code == config.successCode){
|
||||
param.onSuccess(res)
|
||||
}else{
|
||||
param.onError(response.msg || "未知错误")
|
||||
}
|
||||
}).catch(err => {
|
||||
param.onError(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-form-item.is-error .sc-upload-file:deep(.el-upload-dragger) {border-color: var(--el-color-danger);}
|
||||
.sc-upload-file {width: 100%;}
|
||||
.sc-upload-file:deep(.el-upload-list__item) {transition: none !important;}
|
||||
</style>
|
||||
|
|
@ -1,172 +1,211 @@
|
|||
<template>
|
||||
<div class="sc-upload" v-loading="loading" element-loading-background="rgba(0, 0, 0, 0.5)" :style="style">
|
||||
<div v-if="tempImg || img" class="sc-upload-file">
|
||||
<div class="mask">
|
||||
<span class="del" @click.stop="del"><el-icon><el-icon-delete /></el-icon></span>
|
||||
<div class="sc-upload" :class="{'sc-upload-round':round}" :style="style">
|
||||
<div v-if="file && file.status != 'success'" class="sc-upload__uploading">
|
||||
<div class="sc-upload__progress">
|
||||
<el-progress :percentage="file.percentage" :text-inside="true" :stroke-width="16"/>
|
||||
</div>
|
||||
<el-image v-if="fileIsImg" class="image" :src="tempImg || img" :preview-src-list="[img]" fit="cover" hide-on-click-modal append-to-body :z-index="9999"></el-image>
|
||||
<a v-else :href="img" class="file" target="_blank"><el-icon><el-icon-document /></el-icon></a>
|
||||
<el-image class="image" :src="file.tempFile" fit="cover"></el-image>
|
||||
</div>
|
||||
<div v-else class="sc-upload-uploader" @click="fileSelect && showfileSelect()">
|
||||
<el-upload ref="upload" class="uploader" :disabled="fileSelect" :auto-upload="!cropper" :on-change="change" :accept="accept" :action="action" :show-file-list="false" :before-upload="before" :on-success="success" :on-error="error" :http-request="request">
|
||||
<slot>
|
||||
<div v-if="file && file.status=='success'" class="sc-upload__img">
|
||||
<el-image class="image" :src="file.url" :preview-src-list="[file.url]" fit="cover" hide-on-click-modal append-to-body :z-index="9999">
|
||||
<template #placeholder>
|
||||
<div class="sc-upload__img-slot">
|
||||
Loading...
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<div class="sc-upload__img-actions" v-if="!disabled">
|
||||
<span class="del" @click="handleRemove()"><el-icon><el-icon-delete /></el-icon></span>
|
||||
</div>
|
||||
</div>
|
||||
<el-upload v-if="!file" class="uploader" ref="uploader"
|
||||
:auto-upload="cropper?false:autoUpload"
|
||||
:disabled="disabled"
|
||||
:show-file-list="showFileList"
|
||||
:action="action"
|
||||
:accept="accept"
|
||||
:limit="1"
|
||||
:http-request="request"
|
||||
:on-change="change"
|
||||
:before-upload="before"
|
||||
:on-success="success"
|
||||
:on-error="error"
|
||||
:on-exceed="handleExceed"
|
||||
>
|
||||
<slot>
|
||||
<div class="el-upload--picture-card">
|
||||
<div class="file-empty">
|
||||
<el-icon><component :is="icon" /></el-icon>
|
||||
<h4 v-if="title">{{title}}</h4>
|
||||
</div>
|
||||
</slot>
|
||||
</el-upload>
|
||||
</div>
|
||||
<el-dialog title="剪裁" v-model="cropperDialogVisible" :width="580" destroy-on-close>
|
||||
<sc-cropper :src="cropperImg" :compress="compress" :aspectRatio="aspectRatio" ref="cropper"></sc-cropper>
|
||||
</div>
|
||||
</slot>
|
||||
</el-upload>
|
||||
<span style="display:none!important"><el-input v-model="value"></el-input></span>
|
||||
<el-dialog title="剪裁" draggable v-model="cropperDialogVisible" :width="580" @closed="cropperClosed" destroy-on-close>
|
||||
<sc-cropper :src="cropperFile.tempCropperFile" :compress="compress" :aspectRatio="aspectRatio" ref="cropper"></sc-cropper>
|
||||
<template #footer>
|
||||
<el-button @click="cropperDialogVisible=false" >取 消</el-button>
|
||||
<el-button type="primary" @click="cropperSave">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog title="打开" v-model="fileSelectDialogVisible" :width="880" destroy-on-close>
|
||||
<sc-file-select @submit="fileSelectSubmit">
|
||||
<template #do>
|
||||
<el-button @click="fileSelectDialogVisible=false" >取 消</el-button>
|
||||
</template>
|
||||
</sc-file-select>
|
||||
</el-dialog>
|
||||
<span style="display:none!important"><el-input v-model="img"></el-input></span>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import config from "@/config/upload"
|
||||
import { genFileId } from 'element-plus'
|
||||
const scCropper = defineAsyncComponent(() => import('@/components/scCropper'))
|
||||
const scFileSelect = defineAsyncComponent(() => import('@/components/scFileSelect'))
|
||||
import config from "@/config/upload"
|
||||
|
||||
export default {
|
||||
props: {
|
||||
height: {type: Number, default: 120},
|
||||
width: {type: Number, default: 120},
|
||||
modelValue: { type: String, default: "" },
|
||||
height: {type: Number, default: 148},
|
||||
width: {type: Number, default: 148},
|
||||
title: { type: String, default: "" },
|
||||
icon: { type: String, default: "el-icon-plus" },
|
||||
action: { type: String, default: "" },
|
||||
apiObj: { type: Object, default: () => {} },
|
||||
accept: { type: String, default: "image/gif, image/jpeg, image/png" },
|
||||
maxSize: { type: Number, default: config.maxSize },
|
||||
title: { type: String, default: "" },
|
||||
icon: { type: String, default: "el-icon-plus" },
|
||||
fileSelect: { type: Boolean, default: false },
|
||||
maxSize: { type: Number, default: config.maxSizeFile },
|
||||
limit: { type: Number, default: 1 },
|
||||
autoUpload: { type: Boolean, default: true },
|
||||
showFileList: { type: Boolean, default: false },
|
||||
disabled: { type: Boolean, default: false },
|
||||
round: { type: Boolean, default: false },
|
||||
onSuccess: { type: Function, default: () => { return true } },
|
||||
|
||||
cropper: { type: Boolean, default: false },
|
||||
compress: {type: Number, default: 1},
|
||||
aspectRatio: {type: Number, default: NaN},
|
||||
onSuccess: { type: Function, default: () => { return true } }
|
||||
aspectRatio: {type: Number, default: NaN}
|
||||
},
|
||||
components: {
|
||||
scCropper,
|
||||
scFileSelect
|
||||
scCropper
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
fileIsImg: true,
|
||||
img: "",
|
||||
tempImg: "",
|
||||
value: "",
|
||||
file: null,
|
||||
style: {
|
||||
width: this.width + "px",
|
||||
height: this.height + "px"
|
||||
},
|
||||
cropperDialogVisible: false,
|
||||
cropperImg: "",
|
||||
cropperUploadFile: null,
|
||||
fileSelectDialogVisible: false,
|
||||
cropperFile: null
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
modelValue(){
|
||||
this.isImg(this.modelValue)
|
||||
this.img = this.modelValue;
|
||||
modelValue(val){
|
||||
this.value = val
|
||||
this.newFile(val)
|
||||
},
|
||||
img(){
|
||||
this.$emit('update:modelValue', this.img);
|
||||
value(val){
|
||||
this.$emit('update:modelValue', val)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.isImg(this.modelValue)
|
||||
this.img = this.modelValue;
|
||||
this.value = this.modelValue
|
||||
this.newFile(this.modelValue)
|
||||
},
|
||||
methods: {
|
||||
showfileSelect(){
|
||||
this.fileSelectDialogVisible = true
|
||||
},
|
||||
fileSelectSubmit(val){
|
||||
this.img = val
|
||||
this.fileSelectDialogVisible = false
|
||||
newFile(url){
|
||||
if(url){
|
||||
this.file = {
|
||||
status: "success",
|
||||
url: url
|
||||
}
|
||||
}else{
|
||||
this.file = null
|
||||
}
|
||||
},
|
||||
cropperSave(){
|
||||
var uploadFile = this.$refs.upload.uploadFiles[0].raw
|
||||
this.$refs.cropper.getCropFile(file => {
|
||||
this.cropperUploadFile = file
|
||||
this.$refs.upload.submit()
|
||||
}, uploadFile.name, uploadFile.type)
|
||||
|
||||
file.uid = this.cropperFile.uid
|
||||
this.cropperFile.raw = file
|
||||
|
||||
this.file = this.cropperFile
|
||||
this.file.tempFile = URL.createObjectURL(this.file.raw)
|
||||
this.$refs.uploader.submit()
|
||||
|
||||
}, this.cropperFile.name, this.cropperFile.type)
|
||||
this.cropperDialogVisible = false
|
||||
},
|
||||
isImg(fileUrl){
|
||||
var strRegex = "(.jpg|.png|.gif|.jpeg)$";
|
||||
var re = new RegExp(strRegex);
|
||||
if (re.test(fileUrl.toLowerCase())){
|
||||
this.fileIsImg=true;
|
||||
}else{
|
||||
this.fileIsImg=false;
|
||||
}
|
||||
cropperClosed(){
|
||||
URL.revokeObjectURL(this.cropperFile.tempCropperFile)
|
||||
delete this.cropperFile.tempCropperFile
|
||||
},
|
||||
handleRemove(){
|
||||
this.clearFiles()
|
||||
},
|
||||
clearFiles(){
|
||||
URL.revokeObjectURL(this.file.tempFile)
|
||||
this.value = ""
|
||||
this.file = null
|
||||
this.$nextTick(()=>{
|
||||
this.$refs.uploader.clearFiles()
|
||||
})
|
||||
},
|
||||
change(file){
|
||||
if(this.cropper && file.status=='ready'){
|
||||
this.isImg(file.name)
|
||||
if(!this.fileIsImg){
|
||||
const acceptIncludes = ["image/gif", "image/jpeg", "image/png"].includes(file.raw.type)
|
||||
if(!acceptIncludes){
|
||||
this.$notify.warning({
|
||||
title: '上传文件警告',
|
||||
message: '选择的文件非图像类文件'
|
||||
})
|
||||
return false
|
||||
}
|
||||
this.cropperFile = file
|
||||
this.cropperFile.tempCropperFile = URL.createObjectURL(file.raw)
|
||||
this.cropperDialogVisible = true
|
||||
this.cropperImg = URL.createObjectURL(file.raw)
|
||||
return false
|
||||
}
|
||||
this.file = file
|
||||
if(file.status=='ready'){
|
||||
file.tempFile = URL.createObjectURL(file.raw)
|
||||
}
|
||||
},
|
||||
before(file){
|
||||
file = this.cropper ? this.cropperUploadFile : file
|
||||
const acceptIncludes = this.accept.replace(/\s/g,"").split(",").includes(file.type)
|
||||
if(!acceptIncludes){
|
||||
this.$notify.warning({
|
||||
title: '上传文件警告',
|
||||
message: '选择的文件非图像类文件'
|
||||
})
|
||||
this.clearFiles()
|
||||
return false
|
||||
}
|
||||
const maxSize = file.size / 1024 / 1024 < this.maxSize;
|
||||
if (!maxSize) {
|
||||
this.$message.warning(`上传文件大小不能超过 ${this.maxSize}MB!`);
|
||||
return false;
|
||||
this.clearFiles()
|
||||
return false
|
||||
}
|
||||
this.isImg(file.name)
|
||||
this.tempImg = URL.createObjectURL(file);
|
||||
this.loading = true;
|
||||
},
|
||||
success(res){
|
||||
this.loading = false;
|
||||
this.tempImg = "";
|
||||
var os = this.onSuccess(res);
|
||||
if(os!=undefined && os==false){
|
||||
return false;
|
||||
}
|
||||
var response = config.parseData(res);
|
||||
if(response.code != config.successCode){
|
||||
this.$message.warning(response.msg || "上传文件未知错误")
|
||||
}else{
|
||||
this.img = response.src;
|
||||
}
|
||||
handleExceed(files){
|
||||
const file = files[0]
|
||||
file.uid = genFileId()
|
||||
this.$refs.uploader.handleStart(file)
|
||||
},
|
||||
success(res, file){
|
||||
var response = config.parseData(res)
|
||||
file.url = response.src
|
||||
this.value = file.url
|
||||
|
||||
//释放内存删除blob
|
||||
URL.revokeObjectURL(file.tempFile)
|
||||
delete file.tempFile
|
||||
},
|
||||
error(err){
|
||||
this.$nextTick(()=>{
|
||||
this.clearFiles()
|
||||
})
|
||||
this.$notify.error({
|
||||
title: '上传文件错误',
|
||||
title: '上传文件未成功',
|
||||
message: err
|
||||
})
|
||||
this.loading = false;
|
||||
this.tempImg = "";
|
||||
this.img = ""
|
||||
},
|
||||
del(){
|
||||
this.img = ""
|
||||
},
|
||||
request(param){
|
||||
var apiObj = config.apiObj;
|
||||
|
|
@ -174,10 +213,20 @@
|
|||
apiObj = this.apiObj;
|
||||
}
|
||||
const data = new FormData();
|
||||
var file = this.cropper ? this.cropperUploadFile : param.file
|
||||
var file = param.file
|
||||
data.append("file", file);
|
||||
apiObj.post(data).then(res => {
|
||||
param.onSuccess(res)
|
||||
apiObj.post(data, {
|
||||
onUploadProgress: e => {
|
||||
const complete = parseInt(((e.loaded / e.total) * 100) | 0, 10)
|
||||
param.onProgress({percent: complete})
|
||||
}
|
||||
}).then(res => {
|
||||
var response = config.parseData(res);
|
||||
if(response.code == config.successCode){
|
||||
param.onSuccess(res)
|
||||
}else{
|
||||
param.onError(response.msg || "未知错误")
|
||||
}
|
||||
}).catch(err => {
|
||||
param.onError(err)
|
||||
})
|
||||
|
|
@ -186,32 +235,32 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.sc-upload+.sc-upload {margin-left: 10px;}
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
.el-form-item.is-error .sc-upload-uploader {border: 1px dashed #F56C6C;}
|
||||
.el-form-item.is-error .sc-upload .el-upload--picture-card {border-color: var(--el-color-danger);}
|
||||
.sc-upload .el-upload--picture-card {border-radius: 0;}
|
||||
|
||||
.sc-upload {width: 120px;height: 120px;display: inline-block;vertical-align: top;box-sizing: border-box;}
|
||||
.sc-upload .uploader,.sc-upload:deep(.el-upload) {width: 100%;height: 100%;}
|
||||
|
||||
.sc-upload-file {position: relative;width: 100%;height: 100%;}
|
||||
.sc-upload-file .mask {display: none;position: absolute;top:0px;right:0px;line-height: 1;z-index: 1;}
|
||||
.sc-upload-file .mask span {display: inline-block;width: 25px;height:25px;line-height: 23px;text-align: center;cursor: pointer;color: #fff;}
|
||||
.sc-upload-file .mask span i {font-size: 12px;}
|
||||
.sc-upload-file .mask .del {background: #F56C6C;}
|
||||
.sc-upload-file .image {width: 100%;height: 100%;}
|
||||
.sc-upload-file .image img {vertical-align: bottom;}
|
||||
.sc-upload-file .file {width: 100%;height: 100%;display: flex;flex-direction: column;align-items: center;justify-content: center;border: 1px solid #DCDFE6;}
|
||||
.sc-upload-file .file i {font-size: 30px;color: #409EFF;}
|
||||
.sc-upload-file:hover .mask {display: inline-block;}
|
||||
.sc-upload__img {width: 100%;height: 100%;position: relative;}
|
||||
.sc-upload__img .image {width: 100%;height: 100%;}
|
||||
.sc-upload__img-actions {position: absolute;top:0;right: 0;display: none;}
|
||||
.sc-upload__img-actions span {display: flex;justify-content: center;align-items: center;width: 25px;height:25px;cursor: pointer;color: #fff;}
|
||||
.sc-upload__img-actions span i {font-size: 12px;}
|
||||
.sc-upload__img-actions .del {background: #F56C6C;}
|
||||
.sc-upload__img:hover .sc-upload__img-actions {display: block;}
|
||||
.sc-upload__img-slot {display: flex;justify-content: center;align-items: center;width: 100%;height: 100%;font-size: 12px;background-color: var(--el-fill-color-lighter);}
|
||||
|
||||
.sc-upload-uploader {border: 1px dashed #d9d9d9;box-sizing: border-box;width: 100%;height: 100%;}
|
||||
.sc-upload-uploader:hover {border: 1px dashed #409eff;}
|
||||
.sc-upload-uploader .uploader {width: 100%;height: 100%;}
|
||||
.sc-upload-uploader:deep(.el-upload) {width: 100%;height: 100%;}
|
||||
.sc-upload__uploading {width: 100%;height: 100%;position: relative;}
|
||||
.sc-upload__progress {position: absolute;width: 100%;height: 100%;display: flex;justify-content: center;align-items: center;background-color: var(--el-overlay-color-lighter);z-index: 1;padding:10px;}
|
||||
.sc-upload__progress .el-progress {width: 100%;}
|
||||
.sc-upload__uploading .image {width: 100%;height: 100%;}
|
||||
|
||||
.sc-upload-uploader .file-empty {width: 100%;height: 100%;line-height: 1;display: flex;flex-direction: column;align-items: center;justify-content: center;}
|
||||
.sc-upload-uploader .file-empty i {font-size: 28px;color: #8c939d;}
|
||||
.sc-upload-uploader .file-empty h4 {font-size: 12px;font-weight: normal;color: #8c939d;margin-top: 10px;}
|
||||
.sc-upload .file-empty {width: 100%;height: 100%;display: flex;justify-content: center;align-items: center;flex-direction: column;}
|
||||
.sc-upload .file-empty i {font-size: 28px;}
|
||||
.sc-upload .file-empty h4 {font-size: 12px;font-weight: normal;color: #8c939d;margin-top: 8px;}
|
||||
|
||||
.sc-upload.sc-upload-round {border-radius: 50%;overflow: hidden;}
|
||||
.sc-upload.sc-upload-round .el-upload--picture-card {border-radius: 50%;}
|
||||
.sc-upload.sc-upload-round .sc-upload__img-actions {top: auto;left: 0;right: 0;bottom: 0;}
|
||||
.sc-upload.sc-upload-round .sc-upload__img-actions span {width: 100%;}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,132 +1,98 @@
|
|||
<template>
|
||||
<div class="sc-upload-multiple">
|
||||
<div class="sc-upload-list">
|
||||
<ul>
|
||||
<li v-for="(file, index) in fileList" :key="index">
|
||||
<div v-if="file.status!='success'" class="sc-upload-item" v-loading="true" element-loading-background="rgba(0, 0, 0, 0.5)">
|
||||
<el-image class="image" :src="file.tempImg" fit="cover" :z-index="9999"></el-image>
|
||||
<el-upload ref="uploader" :auto-upload="autoUpload" list-type="picture-card" :disabled="disabled" :action="action" :http-request="request" :file-list="defaultFileList" :show-file-list="showFileList" :accept="accept" :multiple="multiple" :limit="limit" :before-upload="before" :on-success="success" :on-error="error" :on-preview="handlePreview" :on-exceed="handleExceed">
|
||||
<slot>
|
||||
<el-icon><el-icon-plus/></el-icon>
|
||||
</slot>
|
||||
<template #tip>
|
||||
<div v-if="tip" class="el-upload__tip">{{tip}}</div>
|
||||
</template>
|
||||
<template #file="{ file }">
|
||||
<div class="sc-upload-list-item">
|
||||
<el-image class="el-upload-list__item-thumbnail" :src="file.url" fit="cover" :preview-src-list="preview" :initial-index="preview.findIndex(n=>n==file.url)" hide-on-click-modal append-to-body :z-index="9999">
|
||||
<template #placeholder>
|
||||
<div class="sc-upload-multiple-image-slot">
|
||||
Loading...
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<div v-if="!disabled && file.status=='success'" class="sc-upload__item-actions">
|
||||
<span class="del" @click="handleRemove(file)"><el-icon><el-icon-delete /></el-icon></span>
|
||||
</div>
|
||||
<div v-else class="sc-upload-item">
|
||||
<div class="mask">
|
||||
<span class="del" @click.stop="del(index)"><el-icon><el-icon-delete /></el-icon></span>
|
||||
</div>
|
||||
<el-image class="image" :src="file.url" fit="cover" :preview-src-list="preview" hide-on-click-modal append-to-body>
|
||||
<template #placeholder>
|
||||
<div class="image-slot">
|
||||
<el-icon><el-icon-more-filled /></el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<div v-if="file.status=='ready' || file.status=='uploading'" class="sc-upload__item-progress">
|
||||
<el-progress :percentage="file.percentage" :text-inside="true" :stroke-width="16"/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="sc-upload-uploader" @click="fileSelect && showfileSelect()">
|
||||
<el-upload ref="upload" class="uploader" :disabled="fileSelect" :action="action" :accept="accept" multiple :show-file-list="false" :file-list="defaultFileList" :before-upload="before" :on-progress="progress" :on-success="success" :on-change="change" :on-remove="remove" :on-error="error" :http-request="request">
|
||||
<div class="file-empty">
|
||||
<el-icon><component :is="icon" /></el-icon>
|
||||
<h4 v-if="title">{{title}}</h4>
|
||||
</div>
|
||||
</el-upload>
|
||||
</div>
|
||||
<el-dialog title="打开" v-model="fileSelectDialogVisible" :width="880" destroy-on-close>
|
||||
<sc-file-select multiple @submit="fileSelectSubmit">
|
||||
<template #do>
|
||||
<el-button @click="fileSelectDialogVisible=false" >取 消</el-button>
|
||||
</template>
|
||||
</sc-file-select>
|
||||
</el-dialog>
|
||||
</template>
|
||||
</el-upload>
|
||||
<span style="display:none!important"><el-input v-model="value"></el-input></span>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import config from "@/config/upload";
|
||||
const scFileSelect = defineAsyncComponent(() => import('@/components/scFileSelect'))
|
||||
import config from "@/config/upload"
|
||||
import Sortable from 'sortablejs'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
modelValue: { type: String, default: "" },
|
||||
tip: { type: String, default: "" },
|
||||
action: { type: String, default: "" },
|
||||
apiObj: { type: Object, default: () => {} },
|
||||
accept: { type: String, default: "image/gif, image/jpeg, image/png" },
|
||||
maxSize: { type: Number, default: config.maxSize },
|
||||
title: { type: String, default: "" },
|
||||
icon: { type: String, default: "el-icon-plus" },
|
||||
fileSelect: { type: Boolean, default: false }
|
||||
},
|
||||
components: {
|
||||
scFileSelect
|
||||
maxSize: { type: Number, default: config.maxSizeFile },
|
||||
limit: { type: Number, default: 0 },
|
||||
autoUpload: { type: Boolean, default: true },
|
||||
showFileList: { type: Boolean, default: true },
|
||||
multiple: { type: Boolean, default: true },
|
||||
disabled: { type: Boolean, default: false },
|
||||
draggable: { type: Boolean, default: false },
|
||||
onSuccess: { type: Function, default: () => { return true } }
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
value: "",
|
||||
defaultFileList: [],
|
||||
fileList: [],
|
||||
fileSelectDialogVisible: false,
|
||||
defaultFileList: []
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
modelValue(){
|
||||
this.$refs.upload.uploadFiles=this.modelValuetoArr
|
||||
this.fileList = this.modelValuetoArr
|
||||
this.value = this.modelValue
|
||||
modelValue(val){
|
||||
if (val != this.toStr(this.defaultFileList)) {
|
||||
this.defaultFileList = this.toArr(val)
|
||||
this.value = val
|
||||
}
|
||||
},
|
||||
fileList: {
|
||||
handler(){
|
||||
if(this.isAllSuccess){
|
||||
this.$emit('update:modelValue', this.fileListtoStr);
|
||||
}
|
||||
defaultFileList: {
|
||||
handler(val){
|
||||
this.$emit('update:modelValue', this.toStr(val))
|
||||
this.value = this.toStr(val)
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
modelValuetoArr(){
|
||||
return this.toArr(this.modelValue)
|
||||
},
|
||||
fileListtoStr(){
|
||||
return this.toStr(this.fileList)
|
||||
},
|
||||
preview(){
|
||||
return this.fileList.map(v => v.url)
|
||||
},
|
||||
isAllSuccess(){
|
||||
var all_length = this.fileList.length;
|
||||
var success_length = 0
|
||||
this.fileList.forEach(item => {
|
||||
if(item.status == "success"){
|
||||
success_length += 1
|
||||
}
|
||||
})
|
||||
return success_length == all_length
|
||||
return this.defaultFileList.map(v => v.url)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.defaultFileList = this.toArr(this.modelValue);
|
||||
this.fileList = this.toArr(this.modelValue)
|
||||
this.value = this.modelValue
|
||||
this.defaultFileList = this.toArr(this.modelValue)
|
||||
if(!this.disabled && this.draggable){
|
||||
this.rowDrop()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showfileSelect(){
|
||||
this.fileSelectDialogVisible = true
|
||||
},
|
||||
fileSelectSubmit(val){
|
||||
const newval = [...this.modelValue.split(","),...val].join(",")
|
||||
this.$emit('update:modelValue', newval);
|
||||
this.fileSelectDialogVisible = false
|
||||
},
|
||||
//默认值转换为数组
|
||||
toArr(str){
|
||||
var _arr = [];
|
||||
var arr = str.split(",");
|
||||
arr.forEach(item => {
|
||||
if(item){
|
||||
var urlArr = item.split('/');
|
||||
var fileName = urlArr[urlArr.length - 1]
|
||||
_arr.push({
|
||||
name: "F",
|
||||
status: "success",
|
||||
name: fileName,
|
||||
url: item
|
||||
})
|
||||
}
|
||||
|
|
@ -135,42 +101,67 @@
|
|||
},
|
||||
//数组转换为原始值
|
||||
toStr(arr){
|
||||
var _arr = [];
|
||||
arr.forEach(item => {
|
||||
_arr.push(item.url)
|
||||
return arr.map(v => v.url).join(",")
|
||||
},
|
||||
//拖拽
|
||||
rowDrop(){
|
||||
const _this = this
|
||||
const itemBox = this.$refs.uploader.$el.querySelector('.el-upload-list')
|
||||
Sortable.create(itemBox, {
|
||||
handle: ".el-upload-list__item",
|
||||
animation: 200,
|
||||
ghostClass: "ghost",
|
||||
onEnd({ newIndex, oldIndex }) {
|
||||
const tableData = _this.defaultFileList
|
||||
const currRow = tableData.splice(oldIndex, 1)[0]
|
||||
tableData.splice(newIndex, 0, currRow)
|
||||
}
|
||||
})
|
||||
var str = _arr.join(",")
|
||||
return str;
|
||||
},
|
||||
before(file){
|
||||
if(!['image/jpeg','image/png','image/gif'].includes(file.type)){
|
||||
this.$message.warning(`选择的文件类型 ${file.type} 非图像类文件`);
|
||||
return false;
|
||||
}
|
||||
const maxSize = file.size / 1024 / 1024 < this.maxSize;
|
||||
if (!maxSize) {
|
||||
this.$message.warning(`上传文件大小不能超过 ${this.maxSize}MB!`);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
change(file, fileList){
|
||||
file.tempImg = URL.createObjectURL(file.raw);
|
||||
this.fileList = fileList
|
||||
},
|
||||
success(res, file){
|
||||
var response = config.parseData(res);
|
||||
var os = this.onSuccess(res, file)
|
||||
if(os!=undefined && os==false){
|
||||
return false
|
||||
}
|
||||
var response = config.parseData(res)
|
||||
file.name = response.fileName
|
||||
file.url = response.src
|
||||
},
|
||||
progress(){
|
||||
|
||||
},
|
||||
remove(){
|
||||
|
||||
},
|
||||
error(err){
|
||||
this.$notify.error({
|
||||
title: '上传文件错误',
|
||||
title: '上传文件未成功',
|
||||
message: err
|
||||
})
|
||||
},
|
||||
del(index){
|
||||
this.fileList.splice(index, 1);
|
||||
beforeRemove(uploadFile){
|
||||
return this.$confirm(`是否移除 ${uploadFile.name} ?`, '提示', {
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
return true
|
||||
}).catch(() => {
|
||||
return false
|
||||
})
|
||||
},
|
||||
handleRemove(file){
|
||||
this.$refs.uploader.handleRemove(file)
|
||||
//this.defaultFileList.splice(this.defaultFileList.findIndex(item => item.uid===file.uid), 1)
|
||||
},
|
||||
handleExceed(){
|
||||
this.$message.warning(`当前设置最多上传 ${this.limit} 个文件,请移除后上传!`)
|
||||
},
|
||||
handlePreview(uploadFile){
|
||||
window.open(uploadFile.url)
|
||||
},
|
||||
request(param){
|
||||
var apiObj = config.apiObj;
|
||||
|
|
@ -178,9 +169,20 @@
|
|||
apiObj = this.apiObj;
|
||||
}
|
||||
const data = new FormData();
|
||||
data.append("file", param.file);
|
||||
apiObj.post(data).then(res => {
|
||||
param.onSuccess(res)
|
||||
var file = param.file
|
||||
data.append("file", file);
|
||||
apiObj.post(data, {
|
||||
onUploadProgress: e => {
|
||||
const complete = parseInt(((e.loaded / e.total) * 100) | 0, 10)
|
||||
param.onProgress({percent: complete})
|
||||
}
|
||||
}).then(res => {
|
||||
var response = config.parseData(res);
|
||||
if(response.code == config.successCode){
|
||||
param.onSuccess(res)
|
||||
}else{
|
||||
param.onError(response.msg || "未知错误")
|
||||
}
|
||||
}).catch(err => {
|
||||
param.onError(err)
|
||||
})
|
||||
|
|
@ -190,38 +192,18 @@
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.el-form-item.is-error .sc-upload-uploader {border: 1px dashed #F56C6C;}
|
||||
|
||||
.sc-upload-multiple {display: inline-block;}
|
||||
|
||||
|
||||
.sc-upload-list {display: inline-block;}
|
||||
.sc-upload-list li {list-style: none;display: inline-block;width: 120px;height: 120px;margin-right: 10px;vertical-align: top;box-sizing: border-box;}
|
||||
|
||||
.sc-upload-item {position: relative;width: 100%;height: 100%;}
|
||||
.sc-upload-item .mask {display: none;position: absolute;top:0px;right:0px;line-height: 1;z-index: 1;}
|
||||
.sc-upload-item .mask span {display: inline-block;width: 25px;height:25px;line-height: 23px;text-align: center;cursor: pointer;color: #fff;}
|
||||
.sc-upload-item .mask span i {font-size: 12px;}
|
||||
.sc-upload-item .mask .del {background: #F56C6C;}
|
||||
|
||||
.sc-upload-item:hover .mask {display: inline-block;}
|
||||
|
||||
|
||||
.sc-upload-list .image {width: 100%;height: 100%;}
|
||||
|
||||
.sc-upload-list .image-slot {display: flex;justify-content: center;align-items: center;width: 100%;height: 100%;background: #f5f7fa;color: #909399;}
|
||||
.sc-upload-list .image-slot i {font-size: 20px;}
|
||||
|
||||
.sc-upload-uploader {border: 1px dashed #d9d9d9;width: 120px;height: 120px;display: inline-block;vertical-align: top;box-sizing: border-box;}
|
||||
.sc-upload-uploader:hover {border: 1px dashed #409eff;}
|
||||
.sc-upload-uploader .uploader {width: 100%;height: 100%;}
|
||||
.sc-upload-uploader:deep(.el-upload) {width: 100%;height: 100%;}
|
||||
|
||||
|
||||
.sc-upload-uploader .file-empty {width: 100%;height: 100%;line-height: 1;display: flex;flex-direction: column;align-items: center;justify-content: center;}
|
||||
.sc-upload-uploader .file-empty i {font-size: 28px;color: #8c939d;}
|
||||
.sc-upload-uploader .file-empty h4 {font-size: 12px;font-weight: normal;color: #8c939d;margin-top: 10px;}
|
||||
|
||||
|
||||
.el-form-item.is-error .sc-upload-multiple:deep(.el-upload--picture-card) {border-color: var(--el-color-danger);}
|
||||
:deep(.el-upload-list__item) {transition:none;border-radius: 0;}
|
||||
.sc-upload-multiple:deep(.el-upload-list__item.el-list-leave-active) {position: static!important;}
|
||||
.sc-upload-multiple:deep(.el-upload--picture-card) {border-radius: 0;}
|
||||
.sc-upload-list-item {width: 100%;height: 100%;position: relative;}
|
||||
.sc-upload-multiple .el-image {display: block;}
|
||||
.sc-upload-multiple .el-image:deep(img) {-webkit-user-drag: none;}
|
||||
.sc-upload-multiple-image-slot {display: flex;justify-content: center;align-items: center;width: 100%;height: 100%;font-size: 12px;}
|
||||
.sc-upload-multiple .el-upload-list__item:hover .sc-upload__item-actions{display: block;}
|
||||
.sc-upload__item-actions {position: absolute;top:0;right: 0;display: none;}
|
||||
.sc-upload__item-actions span {display: flex;justify-content: center;align-items: center;;width: 25px;height:25px;cursor: pointer;color: #fff;}
|
||||
.sc-upload__item-actions span i {font-size: 12px;}
|
||||
.sc-upload__item-actions .del {background: #F56C6C;}
|
||||
.sc-upload__item-progress {position: absolute;width: 100%;height: 100%;top: 0;left: 0;background-color: var(--el-overlay-color-lighter);}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -6,9 +6,12 @@ export default {
|
|||
apiObj: API.common.upload, //上传请求API对象
|
||||
successCode: 200, //请求完成代码
|
||||
maxSize: 10, //最大文件大小 默认10MB
|
||||
apiObjFile: API.common.uploadFile, //附件上传请求API对象
|
||||
maxSizeFile: 10, //最大文件大小 默认10MB
|
||||
parseData: function (res) {
|
||||
return {
|
||||
code: res.code, //分析状态字段结构
|
||||
fileName: res.data.fileName,//分析文件名称
|
||||
src: res.data.src, //分析图片远程地址结构
|
||||
msg: res.message //分析描述字段结构
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import scTable from './components/scTable'
|
|||
import scFilterBar from './components/scFilterBar'
|
||||
import scUpload from './components/scUpload'
|
||||
import scUploadMultiple from './components/scUpload/multiple'
|
||||
import scUploadFile from './components/scUpload/file'
|
||||
import scFormTable from './components/scFormTable'
|
||||
import scTableSelect from './components/scTableSelect'
|
||||
import scPageHeader from './components/scPageHeader'
|
||||
|
|
@ -45,6 +46,7 @@ export default {
|
|||
app.component('scFilterBar', scFilterBar);
|
||||
app.component('scUpload', scUpload);
|
||||
app.component('scUploadMultiple', scUploadMultiple);
|
||||
app.component('scUploadFile', scUploadFile);
|
||||
app.component('scFormTable', scFormTable);
|
||||
app.component('scTableSelect', scTableSelect);
|
||||
app.component('scPageHeader', scPageHeader);
|
||||
|
|
|
|||
|
|
@ -1,32 +1,54 @@
|
|||
<template>
|
||||
<el-main>
|
||||
|
||||
<el-card shadow="never" header="基础示例">
|
||||
<sc-upload v-model="imgurl"></sc-upload>
|
||||
<sc-upload v-model="imgurl2" title="自定义标题" icon="el-icon-picture"></sc-upload>
|
||||
<sc-upload v-model="imgurl3" :apiObj="uploadApi" accept=".xls,.xlsx" :on-success="success" :width="220">
|
||||
<div class="custom-empty">
|
||||
<el-icon><el-icon-upload /></el-icon>
|
||||
<p>自定义插槽</p>
|
||||
</div>
|
||||
</sc-upload>
|
||||
<sc-upload v-model="imgurl4" title="开启剪裁" :cropper="true" :compress="1" :aspectRatio="1/1"></sc-upload>
|
||||
<el-card shadow="never" header="文件示例">
|
||||
<sc-upload-file v-model="fileurl" :limit="3" tip="最多上传3个文件,单个文件不要超过10M,请上传xlsx/docx格式文件">
|
||||
<el-button type="primary" icon="el-icon-upload">上传附件</el-button>
|
||||
</sc-upload-file>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never" header="图片卡片示例(已开启拖拽排序)">
|
||||
<sc-upload-multiple v-model="fileurl2" draggable :limit="3" tip="最多上传3个文件,单个文件不要超过10M,请上传图像格式文件"></sc-upload-multiple>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never" header="单图像示例">
|
||||
<el-space wrap :size="8">
|
||||
<sc-upload v-model="fileurl3"></sc-upload>
|
||||
<sc-upload v-model="fileurl4" title="自定义标题" icon="el-icon-picture"></sc-upload>
|
||||
<sc-upload v-model="fileurl5" :apiObj="uploadApi" accept="image/jpg,image/png" :on-success="success" :width="220">
|
||||
<div class="custom-empty">
|
||||
<el-icon><el-icon-upload /></el-icon>
|
||||
<p>自定义插槽</p>
|
||||
</div>
|
||||
</sc-upload>
|
||||
<sc-upload v-model="fileurl6" round icon="el-icon-avatar" title="开启圆形"></sc-upload>
|
||||
<sc-upload v-model="fileurl7" title="开启剪裁" :cropper="true" :compress="1" :aspectRatio="1/1"></sc-upload>
|
||||
</el-space>
|
||||
</el-card>
|
||||
|
||||
|
||||
|
||||
<el-card shadow="never" header="在验证表单中使用">
|
||||
<el-form ref="ruleForm" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="身份证" required>
|
||||
<el-space wrap :size="10">
|
||||
<el-form-item prop="img1">
|
||||
<sc-upload v-model="form.img1" title="人像面"></sc-upload>
|
||||
<el-space wrap :size="8">
|
||||
<el-form-item prop="file1">
|
||||
<sc-upload v-model="form.file1" title="人像面"></sc-upload>
|
||||
</el-form-item>
|
||||
<el-form-item prop="img2">
|
||||
<sc-upload v-model="form.img2" title="国徽面"></sc-upload>
|
||||
<el-form-item prop="file2">
|
||||
<sc-upload v-model="form.file2" title="国徽面"></sc-upload>
|
||||
</el-form-item>
|
||||
</el-space>
|
||||
</el-form-item>
|
||||
<el-form-item label="其他凭证" prop="img3">
|
||||
<sc-upload-multiple v-model="form.img3"></sc-upload-multiple>
|
||||
<el-form-item label="其他凭证" prop="file3">
|
||||
<sc-upload-multiple v-model="form.file3"></sc-upload-multiple>
|
||||
</el-form-item>
|
||||
<el-form-item label="附件" prop="file4">
|
||||
<sc-upload-file v-model="form.file4" :limit="1" drag>
|
||||
<el-icon class="el-icon--upload"><el-icon-upload-filled /></el-icon>
|
||||
<div class="el-upload__text">
|
||||
Drop file here or <em>click to upload</em>
|
||||
</div>
|
||||
</sc-upload-file>
|
||||
</el-form-item>
|
||||
<el-form-item label="日期" prop="date">
|
||||
<el-date-picker type="date" placeholder="选择日期" v-model="form.date"></el-date-picker>
|
||||
|
|
@ -47,26 +69,33 @@
|
|||
data() {
|
||||
return {
|
||||
uploadApi: this.$API.common.upload,
|
||||
imgurl: "img/avatar.jpg",
|
||||
imgurl2: "",
|
||||
imgurl3: "",
|
||||
imgurl4: "",
|
||||
fileurl: "http://www.scuiadmin.com/files/220000198611262243.xlsx,http://www.scuiadmin.com/files/350000201004261875.xlsx",
|
||||
fileurl2: "img/auth_banner.jpg,img/avatar3.gif",
|
||||
fileurl3: "img/auth_banner.jpg",
|
||||
fileurl4: "",
|
||||
fileurl5: "",
|
||||
fileurl6: "",
|
||||
fileurl7: "",
|
||||
form: {
|
||||
img1: "",
|
||||
img2: "",
|
||||
img3: "",
|
||||
file1: "",
|
||||
file2: "",
|
||||
file3: "",
|
||||
file4: "",
|
||||
date: ""
|
||||
},
|
||||
rules: {
|
||||
img1: [
|
||||
file1: [
|
||||
{required: true, message: '请上传', trigger: 'change'}
|
||||
],
|
||||
img2: [
|
||||
file2: [
|
||||
{required: true, message: '请上传', trigger: 'change'}
|
||||
],
|
||||
img3: [
|
||||
file3: [
|
||||
{required: true, message: '请上传', trigger: 'change'}
|
||||
],
|
||||
file4: [
|
||||
{required: true, message: '请上传附件', trigger: 'change'}
|
||||
],
|
||||
date: [
|
||||
{required: true, message: '请选择日期', trigger: 'change'}
|
||||
]
|
||||
|
|
@ -75,12 +104,12 @@
|
|||
},
|
||||
methods: {
|
||||
success(response){
|
||||
this.$alert(`success函数钩子,return false后阻止后续执行,回调参数打开控制台查看`, {
|
||||
this.$alert(`success函数钩子,可用于类似OCR返回信息,return false后阻止后续执行,回调参数打开控制台查看`, {
|
||||
title: "提示",
|
||||
type: "success"
|
||||
})
|
||||
console.log(response);
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
submitForm(){
|
||||
this.$refs.ruleForm.validate((valid) => {
|
||||
|
|
@ -101,9 +130,9 @@
|
|||
|
||||
<style scoped>
|
||||
.el-card+.el-card {margin-top: 15px;}
|
||||
.imglist .el-col+.el-col {margin-left: 8px;}
|
||||
|
||||
.imglist .el-col+.el-col {margin-left: 10px;}
|
||||
.custom-empty {width: 100%;height: 100%;line-height: 1;display: flex;flex-direction: column;align-items: center;justify-content: center;}
|
||||
.custom-empty i {font-size: 30px;color: #8c939d;}
|
||||
.custom-empty p {font-size: 12px;font-weight: normal;color: #8c939d;margin-top: 10px;}
|
||||
.custom-empty {width: 100%;height: 100%;display: flex;flex-direction: column;align-items: center;justify-content: center;background: #8c939d;border-radius:5px;}
|
||||
.custom-empty i {font-size: 30px;color: #fff;}
|
||||
.custom-empty p {font-size: 12px;font-weight: normal;color: #fff;margin-top: 10px;}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue