封装组件实现:目前可以实现的文件格式,包括
图片
,word支持docx
,excel支持xlsx
,还有
<template>
<div class="viewItemFile">
<!-- 预览文件 -->
<el-dialog
width="61%"
class="viewItemFileDialog"
title="预 览"
v-model='dialogVisible'
:before-close="handleClose"
:close-on-click-modal="false"
:close-on-press-escape="false"
>
<div class="image" v-if="props.type == 'JPG' || props.type == 'jpg' || props.type == 'JPEG' || props.type == 'jpeg' || props.type == 'PNG' || props.type == 'png'" >
<div>
<img style="display: block; max-width: 100%; margin: 0 auto" :src="imgUrl" alt="" />
</div>
</div>
<div class="docWrap" v-if="props.type == 'docx'">
<!-- 预览文件的地方(用于渲染) -->
<div ref="file"></div>
</div>
<div v-if="props.type == 'xlsx'" >
<div class="tab">
<el-radio-group size="small" v-model="excel.sheetNameActive" @change="getSheetNameTable">
<el-radio-button v-for="(item,index) in excel.sheetNames" :key="index" :label="item"></el-radio-button>
</el-radio-group>
</div>
<div
style="margin-top: 5px;border: 1px solid #a0a0a0;overflow:auto;">
<div v-html="excel.SheetActiveTable" style="padding: 10px 15px"></div>
</div>
</div>
<div v-if="props.type == 'pdf'">
<iframe
:src="pdfurl"
type="application/x-google-chrome-pdf"
width="100%"
height="1000px"
/>
</div>
</el-dialog>
</div>
</template>
<script setup>
import {ref, nextTick, onMounted, getCurrentInstance, reactive,toRefs} from 'vue'
import * as docx from 'docx-preview'
import XLSX from 'xlsx'
import axios from 'axios';
const { proxy } = getCurrentInstance();
const typeName = ref(props.type);
const imgUrl = ref('');
const srcList = ref();
const loading = ref(false);
const pdfurl = ref('');
const dialogVisible = ref(props.showTime);
const emits = defineEmits();
const emptyTips = ref('暂无内容');
const fullscreen = ref(false);
const data = reactive({
excel: {
// 数据
workbook: {},
// 表名称集合
sheetNames: [],
// 激活项
sheetNameActive: "",
// 当前激活表格
SheetActiveTable: ""
}
})
const props = defineProps({
showTime:{
type:Boolean,
default: false
},
url:{
type:String,
default:''
},
type:{
type:String,
default:'image'
},
clientHeight:{
type:Number,
default:600
}
});
const {excel} = toRefs(data);
onMounted(()=>{
console.log(props.type,'++++')
init(props.type);
})
// 前一个页面调用的init 我在前一个页面根据文件名字后缀已经判断是什么类型的文件了
function init(type) {
typeName.value = type;
if (type == "JPG" || type =='JPEG' || type == 'PNG' || type == 'jpg' || type == 'jpeg') {
axios.request({
method: "GET", //这个不解释了吧
url: props.url, //路径
responseType: "blob", //告诉服务器想到的响应格式
headers: {
Accept: "application/octet-stream",
},
})
.then((res) => {
console.log(res,'image');
if (res) {
let blob = new Blob([res.data], { type: "image/jpg" });
const imageUrl = URL.createObjectURL(blob);
imgUrl.value = imageUrl;
srcList.value = [imageUrl],
loading.value = true;
} else {
// Message.error({ title: "失败", message: "接口请求失败" });
loading.value = false;
}
})
.catch(function (error) {
// Message.error({ title: "失败", message: "接口请求失败" });
console.log(error);
loading.value = false;
});
} else if (type == "pdf") {
axios.request({
method: "GET", //这个不解释了吧
url: props.url,//路径
responseType: "blob", //告诉服务器想到的响应格式
headers: {
"Content-Type": "application/pdf;charset=UTF-8",
},
})
.then((res) => {
console.log(res);
if (res) {
let blob = new Blob([res.data], { type: "application/pdf" });
const url = URL.createObjectURL(blob);
console.log(url);
loading.value = false;
pdfurl.value = url;
} else {
// Message.error({ title: "失败", message: "接口请求失败" });
loading.value = false;
}
})
.catch(function (error) {
// Message.error({ title: "失败", message: "接口请求失败" });
console.log(error);
loading.value = false;
});
} else if (type == "xlsx") {
//表格
axios.request({
method: "GET", //这个不解释了吧
url: props.url, //路径
responseType: "arraybuffer", //告诉服务器想到的响应格式
headers: {
"Content-Type":
"application/vnd.ms-excel;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
}
}).then((res) => {
console.log(res,'res');
if (res) {
const workbook = XLSX.read(new Uint8Array(res.data), {
type: "array",
});
const sheetNames = workbook.SheetNames // 工作表名称集合
excel.value.workbook = workbook
excel.value.sheetNames = sheetNames
excel.value.sheetNameActive = sheetNames[0]
getSheetNameTable(sheetNames[0])
} else {
// Message.error({ title: "失败", message: "接口请求失败" });
loading.value = false;
}
})
.catch(function (error) {
// Message.error({ title: "失败", message: "接口请求失败" });
console.log(error);
loading.value = false;
});
} else if (type == "docx") {
axios.request({
method: "GET", //这个不解释了吧
url: props.url, //路径
responseType: "blob", //告诉服务器想到的响应格式
})
.then((res) => {
console.log(res);
if (res) {
// let docx = require("docx-preview");
docx.renderAsync(res.data, proxy.$refs.file);
} else {
// Message.error({ title: "失败", message: "接口请求失败" });
loading.value = false;
}
})
.catch(function (error) {
// Message.error({ title: "失败", message: "接口请求失败" });
// console.log(error);
loading.value = false;
});
}
dialogVisible.value = true;
}
function getSheetNameTable(sheetName) {
try {
// 获取当前工作表的数据
const worksheet = excel.value.workbook.Sheets[sheetName]
// 转换为数据 1.json数据有些问题,2.如果是html那么样式需修改
let htmlData = XLSX.utils.sheet_to_html(worksheet, {header: '', footer: ''})
htmlData = htmlData === '' ? htmlData : htmlData.replace(//, ')
// 第一行进行改颜色
htmlData = htmlData === '' ? htmlData : htmlData.replace(//, ')
excel.value.SheetActiveTable = htmlData
} catch (e) {
// 如果工作表没有数据则到这里来处理
excel.value.SheetActiveTable = ''
+ emptyTips.value + ''
}
}
function handleClose() {
emits('update',false)
}
</script>
<style lang="scss" scoped>
.viewItemFile {
.image {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
div {
height: 600px;
width: 600px;
}
}
.divContent {
display: flex;
align-items: center;
justify-content: center;
}
v-deep .el-dialog {
margin: 0 !important;
height: 100vh !important;
.el-dialog__footer {
margin-bottom: 30px;
padding: 0px;
}
}
v-deep .el-dialog__body {
height: 96%;
width: 100%;
padding: 0;
overflow: auto;
}
}
.viewItemFile {
.file-pre {
height: calc(100vh - 40px);
padding: 20px;
.table-html-wrap v-deep table {
border-right: 1px solid #e8eaec;
border-bottom: 1px solid #e8eaec;
border-collapse: collapse;
margin: auto;
}
.table-html-wrap v-deep table td {
border-left: 1px solid #e8eaec;
border-top: 1px solid #e8eaec;
white-space: wrap;
text-align: left;
min-width: 100px;
padding: 4px;
}
table {
border-top: 1px solid #EBEEF5;
border-left: 1px solid #EBEEF5;
width: 100%;
overflow: auto;
tr {
height: 44px;
}
td {
min-width: 200px;
max-width: 400px;
padding: 4px 8px;
border-right: 1px solid #EBEEF5;
border-bottom: 1px solid #EBEEF5;
}
}
.el-tabs--border-card {
// height: calc(100vh - 40px);;
}
.el-tabs--border-card > .el-tabs__content {
overflow: auto;
height: calc(100vh - 110px);
}
}
v-deep table {
width: 100% !important;
border-collapse: collapse !important;
border-spacing: 0 !important;
text-align: center !important;
border: 0px !important;
overflow-x: auto !important;
}
v-deep table tr td {
/* border: 1px solid gray !important; */
border-right: 1px solid gray !important;
border-bottom: 1px solid gray !important;
width: 300px !important;
height: 33px !important;
}
/**整体样式 */
v-deep .excel-view-container {
background-color: #ffffff;
}
/**标题样式 */
v-deep .class4Title {
font-size: 22px !important;
font-weight: bold !important;
padding: 10px !important;
}
/**表格表头样式 */
v-deep.class4TableTh {
/* font-size: 14px !important; */
font-weight: bold !important;
padding: 2px !important;
background-color: #ccc !important;
}
}
html body {
width: 100%;
height: 100vh;
margin: 0;
}
</style>
二、总结
总结:通过父组件传给子组件文件的后端地址url
,组件通过文件类型来判断不同文件的接收类型,并且组件通过props.url
来接收就可以了。
你可能感兴趣的:(vue3,pdf,word,excel)