1.表格组件
<template>
<el-table
:data="tableData"
border
style="width: 100%"
:show-header="false"
:span-method="arraySpanMethod"
>
<el-table-column prop="titleOne" align="center" label="1">
<template slot-scope="scope">
<div>
{{ scope.row.titleOne }}
</div>
<div
v-if="scope.row.subheadingOne"
style="color: #999999; font-size: 8px"
>
{{ scope.row.subheadingOne }}
</div>
</template>
</el-table-column>
<el-table-column prop="contOne" label="2">
<template slot-scope="scope">
<div v-if="scope.row.contOne == '' || scope.row.contOne == null">
<div v-if="scope.row.contOne == '0'">
{{ scope.row.contOne }}
</div>
<div v-else style="color: red">未上报</div>
</div>
<div v-else>
<div
v-if="'img' in scope.row && scope.row.img[0]"
style="display: flex; flex-wrap: wrap"
>
<div v-for="(item, index) in scope.row.contOne" :key="index">
<div
v-if="
[
'pdf',
'doc',
'docx',
'jpg',
'jpeg',
'png',
'xls',
'xlsx',
].indexOf(getFileType(item.url)) != -1
"
>
<!-- {{scope.row}}
<a :href="item.url" download style="margin-left: 10px;">11{{
item.name
}}</a> -->
<span class="donnw" @click="courseDownload(item.url, item.name)">
{{ item.name }}
</span>
</div>
<div
v-if="['jpg', 'jpeg', 'png'].indexOf(getFileType(item)) != -1"
>
<el-image
:src="item"
fit="contain"
style="width: 100px; height: 120px; margin-left: 10px"
:preview-src-list="[item]"
>
<div slot="error" class="image-slot">
<div
style="
width: 100px;
height: 120px;
background-color: #f6f6f6;
font-size: 30px;
text-align: center;
line-height: 120px;
"
>
<i class="el-icon-picture-outline"></i>
</div>
</div>
</el-image>
</div>
</div>
</div>
<div v-else>
<div v-if="scope.row.slot && scope.row.slot[0]">
<slot :name="scope.row.contOneSlot"></slot>
</div>
<div v-else v-html="scope.row.contOne">
<!-- 2222 {{ scope.row.contOne }} -->
</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="titleTwo" align="center" label="3">
<template slot-scope="scope">
<div>
{{ scope.row.titleTwo }}
</div>
<div
v-if="scope.row.subheadingTow"
style="color: #999999; font-size: 8px"
>
{{ scope.row.subheadingTow }}
</div>
</template>
</el-table-column>
<el-table-column prop="contTow" label="4">
<template slot-scope="scope">
<div v-if="scope.row.contTow == '' || scope.row.contTow == null">
<div v-if="scope.row.contTow == '0'">
{{ scope.row.contTow }}
</div>
<div v-else style="color: red">未上报</div>
</div>
<div v-else>
<div v-if="'img' in scope.row && scope.row.img[1]">
<div
v-for="(item, index) in scope.row.contTow"
:key="index"
style="display: flex; flex-wrap: wrap"
>
<div
v-if="
[
'pdf',
'doc',
'docx',
'jpg',
'jpeg',
'png',
'xls',
'xlsx',
].indexOf(getFileType(item.url)) != -1
"
>
<!-- {{scope.row}}
<a :href="item.url" download style="margin-left: 10px;">11{{
item.name
}}</a> -->
<span class="donnw" @click="courseDownload(item.url, item.name)">
{{ item.name }}
</span>
</div>
<div
v-if="['jpg', 'jpeg', 'png'].indexOf(getFileType(item)) != -1"
>
<el-image
:src="item"
fit="contain"
style="width: 100px; height: 120px; margin-left: 10px"
:preview-src-list="[item]"
>
<div slot="error" class="image-slot">
<div
style="
width: 100px;
height: 120px;
background-color: #f6f6f6;
font-size: 30px;
text-align: center;
line-height: 120px;
"
>
<i class="el-icon-picture-outline"></i>
</div>
</div>
</el-image>
</div>
</div>
</div>
<div v-else>
<div v-if="scope.row.slot && scope.row.slot[1]">
<slot :name="scope.row.contTowSlot"></slot>
</div>
<div v-else v-html="scope.row.contTow">
<!-- {{ scope.row.contTow }} -->
</div>
</div>
</div>
</template>
</el-table-column>
</el-table>
</template>
<script>
import axios from "axios";
export default {
props: {
data: {
type: Array,
default: function () {
return [];
},
},
},
data() {
return {
tableData: this.data,
};
},
watch: {
data: {
handler(newName, oldName) {
console.log("obj.a changed");
this.tableData = newName;
},
immediate: true,
deep: true,
},
},
methods: {
courseDownload(url, filename) {
this.getBlob(url, (blob) => {
this.saveAs(blob, filename);
});
},
getBlob(url, cb) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "blob";
xhr.onload = function () {
if (xhr.status === 200) {
cb(xhr.response);
}
};
xhr.send();
},
saveAs(blob, filename) {
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(blob, filename);
} else {
var link = document.createElement("a");
var body = document.querySelector("body");
link.href = window.URL.createObjectURL(blob);
link.download = filename;
// fix Firefox
link.style.display = "none";
body.appendChild(link);
link.click();
body.removeChild(link);
window.URL.revokeObjectURL(link.href);
}
},
down(url, name) {
const blob = new Blob([url], {
//this.detailinfo是后台返回给前台的文档下载链接
type: "application/msword",
});
const objectUrl = URL.createObjectURL(blob);
const link = document.createElement("a"); //我们用模拟q标签点击事件
const fname = name; //下载文件的名字
link.setAttribute("download", fname);
link.href = url;
link.target = "_blank";
link.click(); //点击
// document.body.removeChild(link); // 下载完成移除元素
// window.URL.revokeObjectURL(URL); // 释放掉blob对象
// 针对移动端对于blob兼容不友好,华为手机无反应另外解决 pc端一切正常
// axios.get(url, {
// responseType: 'blob',
// })
// .then((res) => {
// const blob = new Blob([res.data], {
// type: 'application/vnd.ms-excel'
// }) // 构造一个blob对象来处理数据,并设置文件类型
// if (window.navigator.msSaveOrOpenBlob) {
// // 兼容IE10
// navigator.msSaveBlob(blob, name)
// } else {
// const href = URL.createObjectURL(blob) // 创建新的URL表示指定的blob对象
// const a = document.createElement('a')
// a.style.display = 'none'
// a.href = href // 指定下载链接
// a.download = name // 指定下载文件名
// a.click()
// URL.revokeObjectURL(a.href) // 释放URL对象
// }
// })
},
getFileType(fileName) {
// 后缀获取
let suffix = "";
// 获取类型结果
let result = "";
try {
const flieArr = fileName.split("."); //根据.分割数组
suffix = flieArr[flieArr.length - 1]; //取最后一个
} catch (err) {
//如果fileName为空等.split方法会报错,就走下面的逻辑
suffix = "";
}
// fileName无后缀返回 false
if (!suffix) {
//走catch后返回false
return false;
}
suffix = suffix.toLocaleLowerCase(); //将后缀所有字母改为小写方便操作
/* 这里开始写入需要判断的逻辑体 */
return suffix; //以上的判断逻辑都没return时反馈当前后缀是其他类型文件后缀
},
arraySpanMethod({ row, column, rowIndex, columnIndex }) {
// console.log("222")
if (row.maxRows) {
if (rowIndex >= 0) {
if (columnIndex === 1) {
return [1, 4];
} else if (columnIndex === 1) {
return [0, 4];
}
}
}
},
},
};
</script>
<style type="text/css" scoped="scoped">
.donnw {
color: #0055ff;
margin-right: 10px;
}
</style>
数据转换js文件
contOne:eval(“row.$”+item.prop),
export const formSafetyTabel = (row,tableOption, myexcel = "myexcel") => {
/**
* 方法使用办法
*
* img:true 代表图片文件
* rowViewDisplay:true 表示 不显示在表格
* zdyslot:true 表示 表格需要自定义
* slotName:'name' name 表示自定义的slot name
* maxRows:true 表示换行
* zdyimg:true自定义图片
*
* 注意 :对应dicURL 和 dicdata 图片 无法进行自定义 slot
*
* ***/
let rDate = [];
tableOption.column.map(item => {
// console.log(item)
// 1 先判断 viewDisplay 是否为false 如果是false 就可以在上面显示 如果是都不想显示则加上 rowViewDisplay 为true 在column中加
// console.log(item.zdyViewDisplay)
if (item.prop != myexcel) {
if (!item.viewDisplay && !item.rowViewDisplay) {
//判断是否需要换行
if ((item.span == 24 || item.maxRows)) {
// 换行
//1. 判断是否使用dicurl 或者dicDate
if (item.dicUrl != undefined || item.dicData != undefined) {
//使用
rDate.push({
titleOne: item.label,
contOne: row. ['$' + item.prop],
maxRows: true
})
} else if (item.type == 'upload' || item.zdyimg) {
// 是 图片 文件上传 的内容部分 zdyimg 自定义的为return true;
// 先判断是字符串还是数组
rDate.push({
titleOne: item.label,
contOne: row.[item.prop].constructor == Array ? row. [item.prop] : [row. [item.prop]],
img: true,
maxRows: true
})
} else if (item.zdyslot) {
rDate.push({
titleOne: item.label,
contOne: row.[item.prop],
slot: true,
slotName: item.slotName,
maxRows: true
})
} else {
rDate.push({
titleOne: item.label,
contOne: row.[item.prop],
maxRows: true
})
}
} else {
//不换行
if (item.dicUrl != undefined || item.dicData != undefined) {
//使用 dicUrl 或者 dicData
rDate.push({
titleOne: item.label,
contOne: row.['$' + item.prop],
slot: true,
slotName: item.slotName,
})
} else if (item.type == 'upload' || item.zdyimg) {
// 是 图片 文件上传 的内容部分 zdyimg 自定义的为return true;
// 先判断是字符串还是数组
rDate.push({
titleOne: item.label,
contOne: row.[item.prop].constructor == Array ? row. [item.prop] : [row. [item.prop]],
img: true,
})
} else if (item.zdyslot) {
// alert(item.label)
rDate.push({
titleOne: item.label,
contOne: row.[item.prop],
slot: true,
slotName: item.slotName,
})
} else {
rDate.push({
titleOne: item.label,
contOne: row.[item.prop],
})
}
}
}
}
})
/****
*
* 下面是为了将不是 maxRows 的数据结合再一起
*/
console.log(rDate, 'rDate')
let data = [];//最后提交数据
let dataCount = 0;// true表示可以添加到上一个元素
rDate.map((item, index) => {
if (index == 0) {
if (item.img) {
item.img = [true, false];
}
if (item.slot) {
item.slot = [true, false];
item.contOneSlot = item.slotName;
}
data.push(item);
dataCount++;
} else {
if (item.maxRows != undefined && item.maxRows) {
if (item.img) {
data.push({
...item,
img: [true, false],
});
dataCount++;
} else if (item.slot) {
data.push({
...item,
slot: [true, false],
contOneSlot: item.slotName
});
dataCount++;
} else {
data.push(item);
dataCount++;
}
} else {
if (data[dataCount - 1].maxRows != undefined && data[dataCount - 1].maxRows) {
if (item.img) {
data.push({
...item,
img: [true, false],
});
dataCount++;
} else if (item.slot) {
data.push({
...item,
slot: [true, false],
contOneSlot: item.slotName
});
dataCount++;
} else {
data.push(item);
dataCount++;
}
} else {
if (data[dataCount - 1].titleTwo != undefined) {
if (item.img) {
data.push({
...item,
img: [true, false],
});
dataCount++;
} else if (item.slot) {
data.push({
...item,
slot: [true, false],
contOneSlot: item.slotName
});
dataCount++;
} else {
data.push(item);
dataCount++;
}
} else {
if (item.img) {
// item.img = [data[dataCount - 1].img[0], true];
data[dataCount - 1] = {
...data[dataCount - 1],
titleTwo: item.titleOne,
contTow: item.contOne,
img:[data[dataCount - 1].img[0], true]
}
} else if (item.slot) {
// item.slot = [data[dataCount - 1].slot[0], true];
// item.contTowSlot = item.slotName;
data[dataCount - 1] = {
...data[dataCount - 1],
titleTwo: item.titleOne,
contTow: item.contOne,
slot:[data[dataCount - 1].slot[0], true],
contTowSlot: item.contTowSlot
}
} else {
data[dataCount - 1] = {
...data[dataCount - 1],
titleTwo: item.titleOne,
contTow: item.contOne,
}
}
}
}
}
}
})
console.log(data, 'data')
return data;
}
使用步骤
1 导入对应的组件和js文件
import excelTable from '@/components/exce-table/index.vue';
import {
formSafetyTabel
} from '@/components/exce-table/table.js';
2 修改对应avue 表格的js column 第一个插入对应数据
{
labelWidth: 0,
prop: "myexcel",
formslot: true,
span: 24,
hide: true,
editDisplay: false,
addDisplay: false,
}
3 调用方法
getExcelData(row) {
return formSafetyTabel(row,this.tableOption)
},
<template slot-scope="{row,index}" slot="myexcelForm">
<excel-table :data="getExcelData(row)">
</excel-table>
</template>
4 合并
<template>
<el-table :data="tableData" border style="width: 100%" :show-header="false" :span-method="arraySpanMethod">
<el-table-column prop="titleOne" align="center" label="1">
<template slot-scope="scope">
<div>
{{ scope.row.titleOne }}
</div>
<div v-if="scope.row.subheadingOne" style="color: #999999; font-size: 8px">
{{ scope.row.subheadingOne }}
</div>
</template>
</el-table-column>
<el-table-column prop="contOne" label="2">
<template slot-scope="scope">
<div v-if="scope.row.contOne == '' || scope.row.contOne == null">
<div v-if="scope.row.contOne == '0'">
{{ scope.row.contOne }}
</div>
<div v-else style="color: red">未上报</div>
</div>
<div v-else>
<div v-if="'img' in scope.row && scope.row.img[0]" style="display: flex; flex-wrap: wrap">
<div v-for="(item, index) in scope.row.contOne" :key="index">
<div v-if="
[
'pdf',
'doc',
'docx',
'jpg',
'jpeg',
'png',
'xls',
'xlsx',
].indexOf(getFileType(item.url)) != -1
">
<!-- {{scope.row}}
<a :href="item.url" download style="margin-left: 10px;">11{{
item.name
}}</a> -->
<span class="donnw" @click="courseDownload(item.url, item.name)">
{{ item.name }}
</span>
</div>
<div v-if="['jpg', 'jpeg', 'png'].indexOf(getFileType(item)) != -1">
<el-image :src="item" fit="contain"
style="width: 100px; height: 120px; margin-left: 10px" :preview-src-list="[item]">
<div slot="error" class="image-slot">
<div style="
width: 100px;
height: 120px;
background-color: #f6f6f6;
font-size: 30px;
text-align: center;
line-height: 120px;
">
<i class="el-icon-picture-outline"></i>
</div>
</div>
</el-image>
</div>
</div>
</div>
<div v-else>
<div v-if="scope.row.slot && scope.row.slot[0]">
<slot :name="scope.row.contOneSlot"></slot>
</div>
<div v-else v-html="scope.row.contOne">
<!-- 2222 {{ scope.row.contOne }} -->
</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="titleTwo" align="center" label="3">
<template slot-scope="scope">
<div>
{{ scope.row.titleTwo }}
</div>
<div v-if="scope.row.subheadingTow" style="color: #999999; font-size: 8px">
{{ scope.row.subheadingTow }}
</div>
</template>
</el-table-column>
<el-table-column prop="contTow" label="4">
<template slot-scope="scope">
<div v-if="scope.row.contTow == '' || scope.row.contTow == null">
<div v-if="scope.row.contTow == '0'">
{{ scope.row.contTow }}
</div>
<div v-else style="color: red">未上报</div>
</div>
<div v-else>
<div v-if="'img' in scope.row && scope.row.img[1]">
<div v-for="(item, index) in scope.row.contTow" :key="index"
style="display: flex; flex-wrap: wrap">
<div v-if="
[
'pdf',
'doc',
'docx',
'jpg',
'jpeg',
'png',
'xls',
'xlsx',
].indexOf(getFileType(item.url)) != -1
">
<!-- {{scope.row}}
<a :href="item.url" download style="margin-left: 10px;">11{{
item.name
}}</a> -->
<span class="donnw" @click="courseDownload(item.url, item.name)">
{{ item.name }}
</span>
</div>
<div v-if="['jpg', 'jpeg', 'png'].indexOf(getFileType(item)) != -1">
<el-image :src="item" fit="contain"
style="width: 100px; height: 120px; margin-left: 10px" :preview-src-list="[item]">
<div slot="error" class="image-slot">
<div style="
width: 100px;
height: 120px;
background-color: #f6f6f6;
font-size: 30px;
text-align: center;
line-height: 120px;
">
<i class="el-icon-picture-outline"></i>
</div>
</div>
</el-image>
</div>
</div>
</div>
<div v-else>
<div v-if="scope.row.slot && scope.row.slot[1]">
<slot :name="scope.row.contTowSlot"></slot>
</div>
<div v-else v-html="scope.row.contTow">
<!-- {{ scope.row.contTow }} -->
</div>
</div>
</div>
</template>
</el-table-column>
</el-table>
</template>
<script>
import axios from "axios";
import {
formSafetyTabel
} from './table.js'
export default {
props: {
// avue 的 tableOption
tableOption: {
type: Object,
default: function() {
return {}
}
},
// 传过来的参数
rowData: {
type: Object,
default: function() {
return {}
}
},
// 自定义名称的名称
tabName:{
type: String,
default:'myexcel'
}
},
data() {
return {
tableData:[],
};
},
watch: {
rowData: {
handler(newName, oldName) {
// row,tableOption, myexcel = "myexcel"
this.tableData = formSafetyTabel(newName,this.tableOption,this.tabName);
},
immediate: true,
deep: true,
},
},
methods: {
courseDownload(url, filename) {
this.getBlob(url, (blob) => {
this.saveAs(blob, filename);
});
},
getBlob(url, cb) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "blob";
xhr.onload = function() {
if (xhr.status === 200) {
cb(xhr.response);
}
};
xhr.send();
},
saveAs(blob, filename) {
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(blob, filename);
} else {
var link = document.createElement("a");
var body = document.querySelector("body");
link.href = window.URL.createObjectURL(blob);
link.download = filename;
// fix Firefox
link.style.display = "none";
body.appendChild(link);
link.click();
body.removeChild(link);
window.URL.revokeObjectURL(link.href);
}
},
down(url, name) {
const blob = new Blob([url], {
//this.detailinfo是后台返回给前台的文档下载链接
type: "application/msword",
});
const objectUrl = URL.createObjectURL(blob);
const link = document.createElement("a"); //我们用模拟q标签点击事件
const fname = name; //下载文件的名字
link.setAttribute("download", fname);
link.href = url;
link.target = "_blank";
link.click(); //点击
// document.body.removeChild(link); // 下载完成移除元素
// window.URL.revokeObjectURL(URL); // 释放掉blob对象
// 针对移动端对于blob兼容不友好,华为手机无反应另外解决 pc端一切正常
// axios.get(url, {
// responseType: 'blob',
// })
// .then((res) => {
// const blob = new Blob([res.data], {
// type: 'application/vnd.ms-excel'
// }) // 构造一个blob对象来处理数据,并设置文件类型
// if (window.navigator.msSaveOrOpenBlob) {
// // 兼容IE10
// navigator.msSaveBlob(blob, name)
// } else {
// const href = URL.createObjectURL(blob) // 创建新的URL表示指定的blob对象
// const a = document.createElement('a')
// a.style.display = 'none'
// a.href = href // 指定下载链接
// a.download = name // 指定下载文件名
// a.click()
// URL.revokeObjectURL(a.href) // 释放URL对象
// }
// })
},
getFileType(fileName) {
// 后缀获取
let suffix = "";
// 获取类型结果
let result = "";
try {
const flieArr = fileName.split("."); //根据.分割数组
suffix = flieArr[flieArr.length - 1]; //取最后一个
} catch (err) {
//如果fileName为空等.split方法会报错,就走下面的逻辑
suffix = "";
}
// fileName无后缀返回 false
if (!suffix) {
//走catch后返回false
return false;
}
suffix = suffix.toLocaleLowerCase(); //将后缀所有字母改为小写方便操作
/* 这里开始写入需要判断的逻辑体 */
return suffix; //以上的判断逻辑都没return时反馈当前后缀是其他类型文件后缀
},
arraySpanMethod({
row,
column,
rowIndex,
columnIndex
}) {
// console.log("222")
if (row.maxRows) {
if (rowIndex >= 0) {
if (columnIndex === 1) {
return [1, 4];
} else if (columnIndex === 1) {
return [0, 4];
}
}
}
},
},
};
</script>
<style type="text/css" scoped="scoped">
.donnw {
color: #0055ff;
margin-right: 10px;
}
</style>