文件上传使用element-ui的el-upload
html部分
<template>
<div :style="{ display: 'flex' }">
<el-upload
v-show="showUpload"
:show-file-list="false"
:before-upload="handleBeforeUpload"
:http-request="onFileChange"
:accept="accept"
:multiple="false"
:file-list="jxd_23FileList"
:on-error="handleError"
ref="commonupload"
style="margin-top: 0"
class="upLoadBtn"
:on-change="fileChangeSize"
on-exceed="handleExceed"
>
<i class="el-icon-upload"></i> 文件上传
</el-upload>
<el-dialog
:visible.sync="showProgress"
v-if="showProgress"
title="文件上传"
append-to-body
width="50%"
:close-on-click-modal="false"
:close-on-click-model="false"
:show-close="false"
>
<el-progress
:text-inside="true"
:stroke-width="20"
:percentage="progress"
></el-progress>
<div slot="footer" class="dialog-footer" v-show="ifSuccess">
<el-button @click="winthDraw">取消</el-button>
</div>
</el-dialog>
</div>
</template>
js部分
<script>
import SparkMD5 from "@/pages/index/components/zCommonViews/spark-md5.min.js";
export default {
props: {
showUpload: {
type: Boolean,
default: true,
},
accept: {
type: String,
default: "",
},
Arr: {
type: Object,
default: function () {
return {};
},
},
//后台返回的接口
staffDeptApi: {
type: Function,
default: function () {
return () => {};
},
},
},
data() {
return {
pId: localStorage.getItem("pId"),
cId: localStorage.getItem("cId"),
files: [],
fileMd5: "",
ifSuccess: false,
fileListData: [],
fileId: "",
fileName: "",
fileType: "",
showProgress: false,
progress: 0,
};
},
methods: {
/** 取消 撤回 */
handleCancel() {
this.progress = 0;
this.showProgress = false;
this.jxd_23FileList = [];
this.files = [];
this.fileListData = [];
const mainFile = this.$refs.commonupload;
if (mainFile && mainFile.length) {
mainFile.forEach((item) => {
item.clearFiles();
});
}
let formData = new FormData();
formData.append("fileId", this.fileId);
this.staffDeptApi[this.Arr.cancelUpload](FormData).then((res) => {
if (res.code == 10000) {
this.$message.success("文件撤回成功");
this.flag = false;
}
});
this.fileId = "";
this.$emit("fileData", this.fileListData);
},
/** 文件状态改变的钩子(添加文件,上传成功,失败都会调用) */
fileChangeSize(file, fileList) {
if (fileList.length > 1) {
fileList.splice(0, 1);
}
},
/** 文件超出限制的钩子 */
handleExceed(files, fileList) {
this.$message.warning(
`已经选择了${files.length}个文件,如需更新先删除已选择文件`
);
},
/** 获取md5 */
getMd5(file) {
return new Promise((resolve, reject) => {
let fildReader = new FileReader();
let spark = new SparkMD5.ArrayBuffer();
fildReader.readAsArrayBuffer(file);
fildReader.onload = (e) => {
spark.append(e.target.result);
let md5 = spark.end();
resolve(md5);
};
});
},
/** 进度条 */
handleProgress() {
this.showProgress = true;
this.progress = 0;
let a = 0;
let time = setInterval(() => {
a = this.processbar();
if (a == 100) {
clearInterval(time);
}
}, 500);
},
//上传失败的方法
handleError(res, file, fileList) {
const self = this;
self.progress = 0;
self.showProgress = false;
this.$message.error("上传失败");
this.active = true;
},
//处理文件流类型
getParamType(val) {
let blobTypes = "";
switch (val) {
case "doc":
blobTypes = "application/msword";
break;
case "docx":
blobTypes =
"application/vnd.openxmlformats-officedocument.wordprocessingml.documnet";
break;
case "xls":
blobTypes = "application/vnd.ms-excel";
break;
case "pdf":
blobTypes = "application/pdf";
break;
case "rar":
blobTypes = "application/rar";
break;
case "7z":
blobTypes = "application/7z";
break;
case "ppt":
blobTypes = "application/vnd.ms-powerpoint";
break;
case "zip":
blobTypes = "application/zip";
break;
case "mp3":
blobTypes = "audio/mpeg";
break;
case "gif":
blobTypes = "image/gif";
break;
case "jpeg":
blobTypes = "image/jpeg";
break;
case "svg":
blobTypes = "image/svg+xml";
break;
case "txt":
blobTypes = "text/plain";
break;
case "avi":
blobTypes = "video/x-msvideo";
break;
case "mpkg":
blobTypes = "application/vnd.apple.installer+xml";
break;
case "pptx":
blobTypes =
"application/vnd.openxmlformats-offcedocument.presentationml.presentation";
break;
case "vsd":
blobTypes = "application/vnd.visio";
break;
case "movie":
blobTypes = "video/x-sgi-movie";
break;
case "mid":
blobTypes = "audio/midi";
break;
case "xlsx":
blobTypes =
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
break;
}
return blobTypes;
},
/** 进度条数值 */
processbar() {
this.progress++;
if (this.progress > 100) {
this.progress = 100;
}
return this.progress;
},
/** 上传之前 */
async handleBeforeUpload(file) {
let self = this;
self.ifSuccess = true;
this.progress = 0;
const filetype = file.name.replace(/.+\./, ".");
if (self.accept.indexOf(filetype) === -1 && self.accept !== "") {
return;
}
self.handleProgress();
self.fileMd5 = await self.getMd5(file);
},
/** 上传事件 */
async onFileChange(file) {
// 清空选中文件
this.$refs.commonupload.clearFiles();
let _this = this;
const filetype = file.file.name.replace(/.+\./, ".");
if (_this.accept.indexOf(filetype) === -1 && _this.accept !== "") {
_this.$message.warning("请上传后缀名为" + _this.accept + "的附件");
return;
} else {
const fileSize = file.file.size;
const fileName = file.file.name;
const maxChunkSize = 10 * 1024 * 1024; // 分片大小
const chunks = Math.ceil(file.file.size / maxChunkSize);
let arr = [];
_this.progress = 0;
if (_this.fileListData.some((item) => item.fileMd5 === _this.fileMd5)) {
_this.$message.warning("请不要重复上传相同的附件");
this.showProgress = false;
return;
}
const queryData = {};
queryData.md5 = _this.fileMd5;
queryData.chunks = chunks;
queryData.fileSize = fileSize;
queryData.fileName = fileName;
queryData.companyId = _this.companyId;
queryData.plantId = _this.plantId;
await _this.staffDeptApi[this.Arr.queryAttachment](queryData).then(
(res) => {
if (res.code === 10000) {
_this.fileId = res.data.id;
if (res.data.exist) {
_this.progress = 100;
_this.handleSuccess();
}
if (!res.data.exist) {
const chunkList = [];
for (let i = 0; i < chunks; i++) {
const start = i * maxChunkSize;
const end = Math.min((i + 1) * maxChunkSize, file.file.size);
chunkList.push(file.file.slice(start, end));
}
chunkList.map((chunk, index) => {
let formData = new FormData();
formData.append("index", index);
formData.append("companyId", _this.companyId);
formData.append("plantId", _this.plantId);
formData.append("companyCode", _this.companyCode);
formData.append("plantCode", _this.plantCode);
formData.append("file", chunk);
formData.append("fileId", _this.fileId);
_this.staffDeptApi[this.Arr.fragmentUpload](formData).then(
(res) => {
// 根据分片进行进度的实时变化
arr.push(index++);
_this.progress = Math.floor((arr.length / chunks) * 100);
if (_this.progress == 100) {
_this.handleSuccess();
}
}
);
});
}
}
}
);
}
},
/** 上传成功 */
handleSuccess() {
const self = this;
if (self.flag) return;
self.fileListData = [];
let tim = setTimeout(() => {
self.progress = 0;
self.showProgress = false;
clearTimeout(tim);
}, 500);
self.$nextTick(() => {
self.staffDeptApi[this.Arr.queryInfomation](self.fileId).then((res) => {
let obj = { ...res.data };
self.fileListData.push({ ...obj });
self.$emit("fileData", self.fileListData);
});
});
},
},
};
</script>
css部分
<style scoped lang="scss">
::v-deep .upBtn {
display: flex;
height: 28px;
border: 1px solid #005aff;
font-size: 14px;
color: #005aff;
width: 80px;
justify-content: center;
align-items: center;
}
.active {
background-color: #fff;
}
::v-deep .upLoadBtn {
display: flex;
height: 28px;
border: 1px solid #005aff;
font-size: 14px;
color: #005aff;
width: 100px;
justify-content: center;
align-items: center;
cursor: pointer;
margin-left: 10px;
border-radius: 5px;
background-color: #fff;
}
</style>
父组件使用
<template>
<div class="box">
<div class="attachmentBox">
<div ref="" class="buttonBox">
<div class="attachText">附件信息</div>
<div class="removeBox">
<!-- 上传文件 -->
<hn-uploadBtn
:accept="accept"
:showUpload="showUpload"
@fileData="fileData"
:Arr="Arr"
:staffDeptApi="staffDeptApi"
>
</hn-uploadBtn>
<el-button
icon="el-icon-delete"
tabindex=""
class="remove"
@click="deleteData"
v-show="showContainer.showDelete"
>
删除
</el-button>
<el-button
class="remove"
:disabled="disabledUpLoad"
v-show="showContainer.showDownload"
@click="debounceUp"
>
<i class="el-icon-bottom"></i>
下载
</el-button>
</div>
<!-- otherWidth 按钮 的整体宽高 accept 支持上传的类型必须有参数 idParam当前行id(子传父) showContainer显示隐藏功能 fileData 推送的文件数据-->
</div>
<div>
<div class="attachTable">
<el-table
class="qua-table"
:height="tableHeight"
v-loading="loading"
:data="jxd_8Data"
@selection-change="selectionChange"
@sort-change="sortChange"
:header-cell-class-name="headerCellClassName"
ref="TableObj"
border
:header-cell-style="{
background: '#D8EDFF',
color: '#181818',
fontSize: '13px',
height: '38px',
}"
:row-style="{ height: '38px' }"
>
<el-table-column
type="selection"
:width="50"
align="center"
></el-table-column>
<el-table-column
prop="attachmentName"
label="文档名称"
fixed="left"
align="left"
header-align="left"
:show-overflow-tooltip="true"
>
<template slot-scope="scope">
<span class="edit-btn-txt" @click="goTypicalDetail(scope.row)">
{{ scope.row.attachmentName }}
</span>
</template>
</el-table-column>
<el-table-column
prop="fileSize"
label="附件大小"
fixed="left"
align="left"
header-align="left"
:show-overflow-tooltip="true"
>
<template slot-scope="scope">
<span class="edit-btn-txt" @click="goTypicalDetail(scope.row)">
{{ scope.row.fileSize }}
</span>
</template>
</el-table-column>
<el-table-column
prop="creator"
label="创建人"
align="left"
header-align="left"
:show-overflow-tooltip="true"
>
<template slot-scope="scope">
{{ scope.row.createdBy }}
</template>
</el-table-column>
<el-table-column
prop="createTime"
label="创建日期"
align="left"
header-align="left"
:show-overflow-tooltip="true"
>
<template slot-scope="scope">
{{ scope.row.createTime }}
</template>
</el-table-column>
<el-table-column
prop=""
label="操作"
align="left"
header-align="left"
>
<template slot-scope="scope">
<el-button class="downBtn" @click="singleDownLoad(scope.row)">
<i class="el-icon-bottom"></i>
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</div>
</template>
<script>
/* @begin definitions # 页面局部定义 */
// 办理过程表格
import hnUploadBtn from "@/pages/index/components/zCommonViews/uploadFile.vue";
import * as staffDeptApi from '@/utils/uploadFile.js';
import moment from "moment";
// 附件删除
import { hussarRequest } from "hussar-base";
import * as opIsTagoutAttachmentModel
from "@/pages/index/api/isolationmanagement/modelisolation/modelview/opistagoutattachmentmodel";
export default {
name: "attachment",
components: {
hnUploadBtn,
},
props: {
jxd_129Show: {
type: Boolean,
default: false,
}
},
data() {
return {
Arr:{
queryAttachment:"queryAttachment", // 检查附件是否存在
fragmentUpload:"fragmentUpload", // 分片上传
cancelUpload:"cancelUpload", // 取消上传
queryInfomation:"queryInfomation" // 查询附件信息
},
staffDeptApi: staffDeptApi,
showUpload: true, // 上传
accept: ".doc,.docx,.xls,.pdf,.ppt,.zip,.rar,.7z,.mp3,.gif,.jpg,.jpeg,.png,.tiff,.svg,.gif,.bmp,.apng,.svg,.txt,.avi,.mpkg,.pptx,.vsd,.movie,.mid,.xlsx",
companyCode: localStorage.getItem("companyCode"),
plantCode: localStorage.getItem("plantCode"),
plantId: localStorage.getItem("plantId"),
companyId: localStorage.getItem("companyId"),
uploadUser: localStorage.getItem(process.env.VUE_APP_USERID),
files: [],
fileMd5: "",
ifSuccess: false,
fileListData: [],
fileId: "",
fileName: "",
fileType: "",
tasks: [],
showProgress: false,
progress: 0,
debounceTimer: null,
disabledUpLoad: false,
selectDataDown: [], // 选中的表格里的数据
timer: null,
//上传文件类型 例.doc,.pdf,.docx,.ppt,.xls,.xlsx,.png,.jpg,.jpeg'
//文件id参数
idParam: "",
//按钮宽度
jxd_8Data : [],
publicBusinessKey: "",
jxd_19ptions: [],
jxd_3Text: "附件信息",
jxd_8BorderStyle: "full",
jxd_8TableLoading: false,
jxd_8TableDataChecked: [],
jxd_14Data: `${sessionStorage.getItem(
process.env.VUE_APP_USERNAME
)}(${sessionStorage.getItem(process.env.VUE_APP_USERID)})`,
delFileDate: [],
jxd_8Disabled: false,
openDelay: 500, //tooltip打开延迟
flowtable: [], //办理历史数据
showContainer: {
showDownload: true, // 下载
showDelete: true, // 删除按钮
}, // 各区域是否展示的字段对象
jxd_389Show: false,
jxd_389ShowClose: true,
jxd_390BorderStyle: "default",
jxd_390TableLoading: false,
jxd_390TableDataChecked: [],
jxd_390Data: [],
jxd_390Disabled: false,
jxd_390OptCols: [
{
field: "personCommon",
colEditComponent: "input",
},
], // 弹出层中对应的字段
progressStatus: "success",
jxd_77TableDataChecked: [],
/* @end data */
};
},
watch: {
/* @begin watch # 自定义侦听器 */
jxd_129Show(newval, oldval) {
let self = this;
if (newval) {
return Object.assign(this.$data,this.$options.data())
}
},
/* @end watch */
},
methods: {
/** 删除 */
// deleteData() {
// const self = this;
// const selectData = self.selectDataDown;
// // selectData.map((item, index) => {
// // self.jxd_8Data.map((subItem, subIndex, arr) => {
// // if (item.id === subItem.id) {
// // if(selectData && selectData.length > 0){
// // arr.splice(0, 1);
// // }
// // }
// // });
// // });
// self.jxd_8Data = JSON.parse(JSON.stringify(self.jxd_8Data));
// },
deleteData() {
const self = this;
// 拿到选中的数据
const selectData = self.selectDataDown;
// 如果选中数据存在
if (selectData.length > 0) {
let deleteRowIds = [];
// 将选中数据遍历
selectData.forEach((item) => {
deleteRowIds.push(item.id);
});
var tableDelete = {
ids: deleteRowIds.join(','),
};
self.$confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
iconClass: "el-icon-info el-icon-info-blue",
customClass: "el-message-box__resetting_Blue",
confirmButtonClass: "el-icon-check ",
cancelButtonClass: "el-icon-close "
}).then(() => {
selectData.map((item, index) => {
self.jxd_8Data.map((subItem, subIndex, arr) => {
if (item.id === subItem.id) {
if(selectData && selectData.length > 0){
arr.splice(0, 1);
}
}
});
});
}).catch(() => {
self.$message({
type: 'info',
message: '已取消删除'
});
});
} else {
self.$message.warning('请至少选择一条数据');
}
},
goTypicalDetail(row) {
let self = this;
let size = Number(row.fileSize.split(" ")[0]);
let zipFormats = ["zip", "rar", "7z"];
let fileFormate = row.attachmentName.split(".").pop().toLowerCase();
if (zipFormats.includes(fileFormate)) {
this.$message.warning("压缩包格式文件不支持预览");
return;
} else if (row.fileSize.indexOf("GB") !== -1 || row.fileSize.indexOf("TB") !== -1) {
this.$message.warning("文件过大,不支持预览");
return;
} else if (row.fileSize.indexOf("MB") !== -1 && size > 10) {
this.$message.warning("文件过大,不支持预览");
return;
} else {
self.previewFile(row.id, row.attachmentName);
}
},
/** 文件预览方法 */
previewFile(id, title) {
const self = this;
var downloadUrl = "";
if (process.env.NODE_ENV == "development") {
downloadUrl = `${process.env.VUE_APP_HUSSAR_DEFAULT_API}/attachment/largeFile/preview?fileId=${id}`;
} else {
downloadUrl = `${process.env.VUE_APP_HUSSAR_DEFAULT_API}/attachment/largeFile/preview?fileId=${id}`;//下载路径
}
const fullfilename = title;
const urlOrign = process.env.VUE_APP_PREVIEWURL + downloadUrl + "&fullfilename=".concat(fullfilename);
const imgFormats = ["jpg", "jpeg", "png", "gif", "bmp", "apng"];
const zipFormats = ["zip", "rar", "7z"];
const fileFormate = fullfilename.split(".").pop().toLowerCase(); //截取到.结尾的pdf文件
if(zipFormats.includes(fileFormate)){
self.$message.warning("压缩包格式文件不支持预览");
return;
}else if(imgFormats.includes(fileFormate)){
const hostName = window.location.origin;
const url = `${hostName}/#/previewImg?url=${downloadUrl}`;//预览图片地址写死
window.open(url,'_blank')
}else{
window.open(process.env.VUE_APP_PREVIEWS.concat('?url=').concat(encodeURIComponent(urlOrign)));
}
},
/** 按钮下载 */
debounceUp() {
const self = this;
if (!self.selectDataDown.length) {
self.$message.error("请选择一条数据");
return;
}
if (this.timer) {
clearTimeout(this.timer);
}
this.timer = setTimeout(function () {
if (self.selectDataDown.length > 1) {
let ids = self.selectDataDown.map((item) => item.id);
ids = ids.join(",");
let param = new FormData();
param.append("fileId", ids);
staffDeptApi['bnttonDownLoad'](param)
.then((result) => {
const blob = new Blob([result], {
type: "application/zip",
});
//下载
const link = document.createElement("a");
link.download = "批量下载";
link.style.display = "none";
link.href = URL.createObjectURL(blob);
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href);
document.body.removeChild(link);
});
} else {
self.singleDownLoad()
}
}, 500);
},
/** 单条下载 */
singleDownLoad(row){
const self = this;
let query = new FormData();
let filetype = ''
let attachmentName = ''
if(row){
query.append("fileId", row.id);
filetype = row.attachmentType;
attachmentName = row.attachmentName;
}else{
query.append("fileId", self.selectDataDown[0].id);
filetype = self.selectDataDown[0].attachmentType;
attachmentName = self.selectDataDown[0].attachmentName;
}
hussarRequest.downloadResource(`/attachment/largeFile/fileDownload`, query).then((result) => {
let blobType = self.getParamType(filetype);
const blob = new Blob([result], {
type: blobType,
});
//下载
const link = document.createElement("a");
link.download = attachmentName;
link.style.display = "none";
link.href = URL.createObjectURL(blob);
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href);
document.body.removeChild(link);
});
},
/** 表格选中数据 */
selectionChange(val) {
if (!val.length) return;
this.selectDataDown = val;
},
/** 理文件流类处型 */
getParamType(val) {
let blobTypes = "";
switch (val) {
case "doc":
blobTypes = "application/msword";
break;
case "docx":
blobTypes =
"application/vnd.openxmlformats-officedocument.wordprocessingml.documnet";
break;
case "xls":
blobTypes = "application/vnd.ms-excel";
break;
case "pdf":
blobTypes = "application/pdf";
break;
case "rar":
blobTypes = "application/rar";
break;
case "7z":
blobTypes = "application/7z";
break;
case "ppt":
blobTypes = "application/vnd.ms-powerpoint";
break;
case "zip":
blobTypes = "application/zip";
break;
case "mp3":
blobTypes = "audio/mpeg";
break;
case "gif":
blobTypes = "image/gif";
break;
case "jpeg":
blobTypes = "image/jpeg";
break;
case "svg":
blobTypes = "image/svg+xml";
break;
case "txt":
blobTypes = "text/plain";
break;
case "avi":
blobTypes = "video/x-msvideo";
break;
case "mpkg":
blobTypes = "application/vnd.apple.installer+xml";
break;
case "pptx":
blobTypes =
"application/vnd.openxmlformats-offcedocument.presentationml.presentation";
break;
case "vsd":
blobTypes = "application/vnd.visio";
break;
case "movie":
blobTypes = "video/x-sgi-movie";
break;
case "mid":
blobTypes = "audio/midi";
break;
case "xlsx":
blobTypes =
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
break;
}
return blobTypes;
},
// 自定义事件 用来接收组件传过来的数据
fileData(val) {
// 对象为空 表格不执行添加的操作
console.log(val,"数据集合")
let ObjectLength = Object.keys({...val[0]})
if(ObjectLength.length === 0) return
this.jxd_8Data.push({ ...val[0]});
},
/* @begin methods # 自定义方法 */
/**
* 附件信息数据加载
* proInsKey: 流程的实例id
* businessKey: 当前业务的主键
*/
getAttatchment(proInsKey, businessKey) {
const self = this;
// 调用获取附件信息表格数据的接口---待补充
self.jxd_388TableLoading = true;
let sysFileInfoNewObj = {
sysFileInfoNewbusinessIdEqual: businessKey,
};
sysFileInfoNew["hussarQuerysysFileInfoNewCondition_1"](sysFileInfoNewObj)
.then((res) => {
if (res.code === "0") {
let convert = [];
res.data.forEach((item) => {
convert.push({
uploadDate: item.uploadDate,
attachmentDir: item.attachmentDir,
attachmentType: item.attachmentType,
uploadPer: item.uploadPer,
businessId: item.businessId,
attachmentName: item.attachmentName,
attachmentSize: item.attachmentSize,
id: item.id,
});
});
self.jxd_8Data = convert;
self.jxd_8TableLoading = false;
} else {
self.$message.error("附件数据请求失败");
self.jxd_388TableLoading = false;
}
})
.catch(function () {
self.$message.error("附件数据请求异常");
self.jxd_388TableLoading = false;
});
},
},
};
</script>
<style scoped lang="scss">
.box {
//background-color: #fff;
}
.attachmentBox {
margin: 10px;
width: 100%;
//padding: 0 10px 10px 0;
background-color: #f1f9ff;
.buttonBox {
display: flex;
justify-content: space-between;
width: 100%;
border-bottom: 1px solid #86c7ff;
background-color: #d8edff;
.attachText {
height: 44px;
font-size: 15px;
font-weight: bold;
line-height: 44px;
padding-left: 20px;
}
.removeBox {
display: flex;
justify-content: end;
padding-top: 10px;
margin-right: 20px;
// ::v-deep .upBtn {
// display: flex;
// height: 28px;
// border: 1px solid #005aff;
// font-size: 14px;
// color: #005aff;
// width: 80px;
// justify-content: center;
// align-items: center;
// }
.active {
background-color: #fff;
}
::v-deep .upLoadBtn {
display: flex;
height: 28px;
border: 1px solid #005aff;
font-size: 14px;
color: #005aff;
width: 100px;
justify-content: center;
align-items: center;
cursor: pointer;
margin-left: 10px;
border-radius: 5px;
background-color: #fff;
}
.remove {
display: flex;
height: 28px;
border: 1px solid #005aff;
font-size: 14px;
color: #005aff;
width: 80px;
justify-content: center;
align-items: center;
margin-left: 10px;
}
}
}
.attachTable {
//padding: 10px 20px 0;
width: 100%;
.el-table {
.edit-btn-txt {
color: #005aff;
cursor: pointer;
}
.downBtn {
background: transparent;
border: none;
font-size: 13px;
color: #005aff;
}
margin-top: 10px;
th,
td {
padding: 0 0 !important;
}
tr:nth-child(even) {
background-color: #f1f9ff;
}
tr:nth-child(odd) {
background-color: #fff;
}
}
}
}
</style>