https://element.eleme.cn/#/zh-CN/component/upload
效果
.upload-container {
display: flex;
align-items: center; /* 垂直居中对齐 */
}
.upload-tip {
margin-left: 10px; /* 根据需要调整间距 */
}
.preview-image {
max-width: 95%;
height: 155px;
padding-left: 2%;
border-radius: 4px;
}
.preview-video {
width: 95%;
height: 155px;
padding-left: 2%;
border-radius: 4px;
}
单个上传:如题干有图片或视频
<el-row>
<el-col :span="8">
<div>
<span v-if="!form.C_FILEGUID">
</span>
<el-image
v-else-if="isImage(form.C_MEDIA_NAME)"
:src="mediaUrl"
:preview-src-list="mediaSrcList" fit="fill"
class="preview-image"
>
</el-image>
<video
v-else
:src="mediaUrl"
controls
:preload="mediaUrl"
class="preview-video"
></video>
</div>
</el-col>
</el-row>
<el-row>
<el-col :span="10">
<el-form-item label="考题附件" >
<el-checkbox-group v-model="form.C_SFTPSP" :disabled="!canEdit" @change="sftpspChange">
<el-checkbox true-label="1" false-label="0" label="图片" name="C_SFTPSP"></el-checkbox>
<el-checkbox true-label="2" false-label="0" label="视频" name="C_SFTPSP"></el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-col>
<el-col :span="14">
<!--
:on-remove="handleRemove"
:on-preview="handlePreview"
-->
<el-upload class="upload-container"
accept=".jpg, .jpeg, .png, .gif, .mp4, .mkv, .mov, .avi, .webm"
action="../upload"
:before-upload="handleBeforeUpload"
:on-success="handleAvatarSuccess"
:show-file-list="showfilelist"
list-type="picture"
:disabled="!canEdit">
<el-button type="text" style="padding-left: 3%;" :disabled = "!canEdit || form.C_SFTPSP=='0' ">上传附件</el-button>
<div slot="tip" class="el-upload__tip" style="margin-left: 15px;">点击上传,只能上传图片或视频,且不超过200Mb</div>
</el-upload>
</el-col>
</el-row>
Table中每行上传,如答案中有图片或视频
<el-main style="width:47%;padding: 1px;height: 100%;border:1px;border:1px solid #ccc;">
<div class="sticky-container">
<el-descriptions title="考题答案配置" style="width: 96%;margin-left: 2%;padding-top: 10px">
</el-descriptions>
</div>
<el-form ref="form_da" :model="form_da" :rules="rules_da"
v-model="form_da" label-width="auto"
style="padding-left: 2%;padding-right: 2%;padding-top: 1px;" @submit.native.prevent>
<el-row>
<el-col :span="24">
<el-form-item label="答案个数" prop="N_DAS" class="custom-flex">
<el-input v-model="form_da.N_DAS" placeholder="请输入答案个数"
maxlength="1"
oninput ="value=value.replace(/[^\d]/g,'')"
@change="addGridRow()"
@input="addGridRow()"
:disabled="!canEditDas" style="width: 120px;">
</el-input>
</el-form-item>
</el-col>
<!--
<el-col :span="10">
<el-form-item >
<el-checkbox v-model="form_da.C_DASJPX" true-label="1" false-label="0" >允许答案随机排布</el-checkbox>
</el-form-item>
</el-col> -->
</el-row>
<el-table :data="tableData" stripe class="table" ref="table"
border="4px" highlight-current-row="true"
fit="false" size="small"
:row-style="{height:'20px'}"
:cell-style="{padding:'0px'}"
:height="mainTableHeight" v-loading="isLoading">
<el-table-column fixed type="index" label="序号" width="50" header-align="center" align="center">
</el-table-column>
<el-table-column prop="C_DABH" label="答案编号" min-width="8%" header-align="center"align="center">
<template slot-scope="scope">
<el-input v-if="canEdit" v-model="scope.row.C_DABH" maxlength="10"></el-input>
<span v-else>{{ scope.row.C_DABH }}</span>
</template>
</el-table-column>
<el-table-column prop="C_DA" label="答案内容" min-width="25%" header-align="center"align="center">
<template slot-scope="scope">
<el-input v-if="canEdit" v-model="scope.row.C_DA"
type="textarea"
style="width: 100%;"
resize='none'
:rows="4"
placeholder="请录入答案内容"
maxlength="600"
show-word-limit
>
</el-input>
<span v-else>{{ scope.row.C_DA }}</span>
</template>
<!--
<template slot-scope="scope">
<span v-if="scope.row[item.prop] !== null">
<el-input v-model="scope.row[item.prop]"></el-input>
</span>
<span style="color: red; cursor: pointer;" v-else @click="deleteColumns(item.prop)">删除列</span>
</template>-->
</el-table-column>
<el-table-column prop="C_SFZQDA" label="正确" min-width="10%" header-align="center"align="center">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.C_SFZQDA" true-label="1" false-label="0"
:disabled="!canEdit"
name="sfzqda" @change="da_sfzqdaCheckboxChange(scope.row)"></el-checkbox>
</template>
</el-table-column>
<el-table-column prop="C_SFTPSP" label="媒体类型" min-width="18%" header-align="center" align="center"
style="display: flex;justify-content: center;align-items: center;height: 100%;">
<template slot-scope="scope">
<el-checkbox-group v-model="scope.row.C_SFTPSP" style="padding-top:25px;" @change="sftpspChange_da(scope.row)">
<el-checkbox true-label="1" false-label="0" label="图片" name="C_SFTPSP_da" :disabled="!canEdit"></el-checkbox>
<el-checkbox true-label="2" false-label="0" label="视频" name="C_SFTPSP_da" :disabled="!canEdit"></el-checkbox>
</el-checkbox-group>
<el-upload class="upload-container"
style="display: flex;justify-content: center;align-items: center;"
accept=".jpg, .jpeg, .png, .gif, .mp4, .mkv, .mov, .avi, .webm"
action="../upload"
:before-upload="(file) => handleBeforeUpload_da(file, scope.row)"
:on-success="handleAvatarSuccess_da"
:show-file-list="showfilelist"
list-type="picture"
:disabled="!canEdit || scope.row.C_SFTPSP === '0'">
<el-button type="text" style="padding-left: 10%;" :disabled = "!canEdit || scope.row.C_SFTPSP=='0' ">上传附件</el-button>
</el-upload>
</template>
</el-table-column>
<el-table-column prop="C_FILEGUID" label="文件" min-width="25%" header-align="center"align="center">
<template slot-scope="scope">
<div>
<span v-if="!scope.row.C_FILEGUID">
</span>
<el-image
v-else-if="isImage(scope.row.C_MEDIA_NAME)"
:src="'../download/'+scope.row.C_FILEGUID"
:preview-src-list="scope.row.mediaSrcList" fit="fill"
class="preview-image"
>
</el-image>
<video
v-else
:src="'../download/'+scope.row.C_FILEGUID"
controls
:preload="'../download/'+scope.row.C_FILEGUID"
class="preview-video"
></video>
</div>
</template>
<!-- update上的 操作按钮 on-remove on-preview
<template slot-scope="scope">
<el-upload ref="upload"
class="upload-container"
accept=".jpg, .jpeg, .png, .gif, .mp4, .mkv, .mov, .avi, .webm"
action="../upload"
:auto-upload="true"
list-type="picture-card"
limit="1"
:file-list="scope.row.fileList"
:before-upload="handleBeforeUpload_da(scope.row)"
:on-success="handleAvatarSuccess_da"
:before-remove="beforeRemove_da"
:on-remove="handleRemove_da"
:on-preview = "handlePreview_da"
:disabled = "scope.row.C_SFTPSP === '0'">
<el-button slot="default" type="text" style="padding-left: 6%;"
:disabled = "!canEdit || scope.row.C_SFTPSP === '0'">上传附件</el-button>
</el-upload>
</template>
-->
<!-- 复写在图片上显示 操作按钮
<template slot-scope="scope">
<el-upload ref="upload"
class="upload-container"
accept=".jpg, .jpeg, .png, .gif, .mp4, .mkv, .mov, .avi, .webm"
action="../upload"
:auto-upload="true"
list-type="picture-card"
limit="1"
:before-upload="handleBeforeUpload_da(scope.row)"
:file-list="scope.row.fileList"
:on-success="handleAvatarSuccess_da"
:on-remove="handleRemove_da"
:disabled = "scope.row.C_SFTPSP === '0'">
<el-button slot="default" type="text" style="padding-left: 6%;"
:disabled = "scope.row.C_SFTPSP === '0'">上传附件</el-button>
<i slot="default" class="el-icon-plus"></i>
<div slot="file" slot-scope="{file}" >
<img class="el-upload-list__item-thumbnail" :src="file.url" alt="" >
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)" >
<i class="el-icon-zoom-in"></i>
</span>
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleDownloadFile(file)" >
<i class="el-icon-download"></i>
</span>
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemoveFile_da(file,scope.row)" >
<i class="el-icon-delete"></i>
</span>
</span>
</div>
</el-upload>
</template>
-->
</el-table-column>
</el-table>
<!--
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog> -->
</el-form>
</el-main>
vm = new Vue({
el: "#app",
data() {
return {
canEdit : true,
imageTypeArr:['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg'],
videoTypeArr:['mp4', 'webm', 'ogg','mkv','mov','avi'],
form: {
C_SFTPSP : "0",//题面是否有图片视频(0 - 无、1 - 图片、2 - 视频)
C_FILEGUID : "",//图片或视频文件编号
C_MEDIA_URL : "",//图片或视频保存地址
C_MEDIA_NAME : "",//媒体名称
C_MEDIA_WIDTH : "",//图片或视频显示宽
C_MEDIA_HEIGHT : "",//图片或视频显示高
},
//是否显示el组件自带的上传文件列表
showfilelist: false,
mediaUrl : "",//"https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
mediaSrcList: [],//["https://fuss10.elemecdn.com/8/27/f01c15bb73e1ef3793e64e6b7bbccjpeg.jpeg"],
initDaRow : {index : "", C_STBH: "", C_DABH: "", C_DA: "",
C_SFTPSP :"0", C_FILEGUID : "", C_SFZQDA : "0",
C_MEDIA_URL : "", C_MEDIA_NAME : "",
mediaSrcList : [], fileList : []},
tableData : [],
currentDaRow: null,
};
},
methods: {
//题干:考题附件 是图片还是视频复选框都不选中时判断
sftpspChange : function(){
if(vm.form.C_SFTPSP == "0" && vm.form.C_FILEGUID){
vm.$confirm('是否删除附件?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
distinguishCancelAndClose: true, // 重要,设置为true才会把右上角X和取消区分开来
closeOnClickModal: false
}).then(function () {
vm.form.C_FILEGUID = "";
vm.form.C_MEDIA_URL = "";
vm.form.C_MEDIA_NAME = "";
vm.form.C_MEDIA_WIDTH = "";
vm.form.C_MEDIA_HEIGHT = "";
vm.mediaUrl = "";
vm.mediaSrcList = [];
}).catch(function (e) {
/*if (e == 'cancel') {
// TODO 取消
} else if(e == 'close') {
// TODO 右上角X的执行逻辑
}*/
if(!vm.form.C_MEDIA_NAME){
return;
}
var tg_media_ext = vm.form.C_MEDIA_NAME.substring(vm.form.C_MEDIA_NAME.lastIndexOf('.') + 1).toLowerCase();
var isPic = vm.imageTypeArr.includes(tg_media_ext);
var isVideo = vm.videoTypeArr.includes(tg_media_ext);
if(isPic){
vm.form.C_SFTPSP = "1";
}
if(isVideo){
vm.form.C_SFTPSP = "2";
}
});
}
},
// 题干 的上传文件前
// 上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。
// 如:限制用户上传的图片格式和大小等。
handleBeforeUpload: function (file) {
var fileType = file.type;
var fileType_ = fileType.toLowerCase();
const isPic = (fileType_ === 'image/png' || fileType_ === 'image/jpeg' || fileType_ === 'image/gif');
const isVideo = (fileType_ === 'video/mp4' || fileType_ === 'video/x-matroska'
|| fileType_ === 'video/quicktime' || fileType_ === 'video/x-msvideo'
|| fileType_ === 'video/webm');
if (!isPic && !isVideo) {
vm.$message({ showClose: true, message: '只能上传图片或视频文件!', type: 'error' });
return false;
}
if (file.size > 200 * 1024 * 1024) {
vm.$message({ showClose: true, message: '文件不能大于200Mb!', type: 'error' });
return false;
}
if(vm.form.C_SFTPSP == "1" && !isPic){
vm.$message({ showClose: true, message: '请上传图片文件!', type: 'error' });
return false;
}
if(vm.form.C_SFTPSP == "2" && !isVideo){
vm.$message({ showClose: true, message: '请上传视频文件!', type: 'error' });
return false;
}
return true;
},
// 题干: 文件上传成功时的钩子
handleAvatarSuccess: function (response, file, fileList) {
//console.log("f_http_req",JSON.stringify(response));
//{data: {"fileGuid":"","fileName":"","savePath":"",...}, code: '0', msg: 'ok', succeed: true}
if(response.code !== '0') {
vm.$message({
type: 'error',
message: response.msg
})
return;
}
var data = response.data;
vm.form.C_FILEGUID = data.fileGuid;//图片或视频文件编号
vm.form.C_MEDIA_URL = data.savePath;//图片或视频保存地址
vm.form.C_MEDIA_NAME= data.fileName;//媒体名称
vm.mediaUrl = file.url;
vm.mediaSrcList = [file.url];
//console.log("f_http_req currentDaRow",JSON.stringify(vm.currentDaRow));
//console.log("f_http_req tableData",JSON.stringify(vm.tableData));
},
//答案中设置是否正确答案 checkbox change后 控制单选题只能有一个正确答案
da_sfzqdaCheckboxChange : function (row) {
//C_STTX 试题题型(0 - 判断题、1 - 单选题、2 - 多选题)
//单选题只能有一个正确答案
if(vm.form.C_STTX == "1" && row.C_SFZQDA == "1"){
for(var i = 0; i < vm.tableData.length; i++){
if(row.index == vm.tableData[i].index){
vm.tableData[i].C_SFZQDA = "1";
}else{
vm.tableData[i].C_SFZQDA = "0";
}
}
}
},
//答案:考题附件 是图片还是视频复选框都不选中时判断
sftpspChange_da : function(row){
if(row.C_SFTPSP == "0" && row.C_FILEGUID){
vm.$confirm('是否删除附件?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
distinguishCancelAndClose: true, // 重要,设置为true才会把右上角X和取消区分开来
closeOnClickModal: false
}).then(function () {
row.C_FILEGUID = "";
row.C_MEDIA_URL = "";
row.C_MEDIA_NAME = "";
//row.C_MEDIA_WIDTH = "";
//row.C_MEDIA_HEIGHT = "";
row.mediaSrcList = [];
row.fileList = [];
}).catch(function (e) {
/*if (e == 'cancel') {
// TODO 取消
} else if(e == 'close') {
// TODO 右上角X的执行逻辑
}*/
if(!row.C_MEDIA_NAME){
return;
}
var tg_media_ext = row.C_MEDIA_NAME.substring(row.C_MEDIA_NAME.lastIndexOf('.') + 1).toLowerCase();
var isPic = vm.imageTypeArr.includes(tg_media_ext);
var isVideo = vm.videoTypeArr.includes(tg_media_ext);
if(isPic){
row.C_SFTPSP = "1";
}
if(isVideo){
row.C_SFTPSP = "2";
}
});
}
},
//答案:上传附件前
handleBeforeUpload_da : function(file,row) {
vm.currentDaRow = row;
var fileType = file.type;
var fileType_ = fileType.toLowerCase();
const isPic = (fileType_ === 'image/png' || fileType_ === 'image/jpeg' || fileType_ === 'image/gif');
const isVideo = (fileType_ === 'video/mp4' || fileType_ === 'video/x-matroska'
|| fileType_ === 'video/quicktime' || fileType_ === 'video/x-msvideo'
|| fileType_ === 'video/webm');
if (!isPic && !isVideo) {
vm.$message({ showClose: true, message: '只能上传图片或视频文件!', type: 'error' });
return false;
}
if (file.size > 200 * 1024 * 1024) {
vm.$message({ showClose: true, message: '文件不能大于200Mb!', type: 'error' });
return false;
}
if(row.C_SFTPSP == "1" && !isPic){
vm.$message({ showClose: true, message: '请上传图片文件!', type: 'error' });
return false;
}
if(row.C_SFTPSP == "2" && !isVideo){
vm.$message({ showClose: true, message: '请上传视频文件!', type: 'error' });
return false;
}
/*return function(){
vm.currentDaRow = row;
return true;
};*/
return true;
},
//答案:上传成功后
handleAvatarSuccess_da :function(response, file, fileList) {
//console.log("handleAvatarSuccess_da",JSON.stringify(response));
//{data: {"fileGuid":"","fileName":"","savePath":"",...}, code: '0', msg: 'ok', succeed: true}
//vm.imageUrl = URL.createObjectURL(file.raw);
if(response.code !== '0') {
vm.$message({
type: 'error',
message: response.msg
})
return;
}
var data = response.data;
vm.currentDaRow.C_FILEGUID = data.fileGuid;//图片或视频文件编号
vm.currentDaRow.C_MEDIA_URL = data.savePath;//图片或视频保存地址
vm.currentDaRow.C_MEDIA_NAME= data.fileName;//媒体名称
vm.currentDaRow.fileList = [{name: vm.currentDaRow.C_MEDIA_NAME, url: "../download/"+vm.currentDaRow.C_FILEGUID, fileguid : vm.currentDaRow.C_FILEGUID }];
vm.currentDaRow.mediaSrcList = ["../download/"+vm.currentDaRow.C_FILEGUID];
//console.log("handleAvatarSuccess_da currentDaRow",JSON.stringify(vm.currentDaRow));
//console.log("handleAvatarSuccess_da tableData",JSON.stringify(vm.tableData));
},
//判断是否为图片类型
isImage: function(src){
if(!src){
return true;
}
const ext = src.substring(src.lastIndexOf('.') + 1).toLowerCase();
return vm.imageTypeArr.includes(ext);
},
},
created: function () {
vm = this;
},
mounted: function () {
}
})