1. 新需求又来了,后台上传pdf,手机微信里要能预览
当时觉得,这个东西牵扯到文件的东西都不怎么好做。
<1>后台上传pdf
因为后台系统使用的是elementui,所以直接就使用elementui的上传组件。感觉elementui 的日期插件有点小小的问题,当我绑定好日期格式,在提交的时候获取的值竟然还是没有格式化的日期,然后我就看教程上的代码还有文档上的api,发现可以绑定一个change,既然我使用的是vue,数据也是双向绑定,但是日期框里面的值要监听change才能拿到转换格式以后的值。就感觉多此一举。然后就是按照官网的例子,操作完了,然后提交请求接口了,歪日,报错了,什么不支持的媒体类型,什么406,,什么后台直接返回不支持类型,我想着我请求头也设置的是multipart/form-data,然后我和后台说为啥报500了啊,你看看是不是你们的问题。人家一口否定了我。当时就在想,请求头也设置了,还有什么设置导致会请求失败么,想来想去也只有请求的数据格式有问题了,后是File格式的数据才行。
async submitUpload() {
let formData = new FormData();
if (this.fileList.length < 1) {
this.$message.error("请上传pdf文件")
} else {
formData.append("file", this.fileList[0].raw);
let res = await savehealthRecord(formData);
console.log("res", res);
if (res.flag) {
this.$message.success("上传成功!");
this.originName = res.originName;
this.accessUrl = res.accessUrl;
this.fileList = [];
}
}
}
<2>前端预览(手机微信预览)
因为我们使用了阿里的oss,所以在上传的时候会返给我地址,我提交的时候又把地址存在我们自己的数据库,微信请求的是这个存储地址。所以一开始我们直接window.location="url",这样做会提示跳转到手机的浏览器,而不是在微信中打开,所以就感觉体验不是很好。希望能在微信中直接开一个页面浏览这些文件内容。 所以参考的 github.com/Lushenggang… 这个哥们的内容。但是稍微的变了一下,他是写了一个组件,把url使用父子传值到pdf渲染页面,因为我想使用路由的方式,所以直接放在Vuex里面,然后使用getter反出来在组件中使用。getter的使用是通过计算属性获取。但是我当时没有在vuex把数据本地化,导致刷新页面以后,数据丢失,页面渲染失败。所以把这个url稍微存储几分钟,防止用户刷新渲染失败。
<template>
<div class="pdf-preview-container">
<!--<iscroll-view :options="{preventDefault: false}" @scrollStart="scroll" class="scroll-view">-->
<navbar ref="navbar"></navbar>
<div
class="pageContainer"
ref="container"
v-for="page in docPages"
:style="{
height: `${pageHeight}px`
}"
:key="page">
<canvas v-show="renderList.includes(page)">
</canvas>
</div>
<div class="notice" v-if="show" @click="gotoTop">
<p>返回顶部</p>
</div>
<div class="refreshPage" v-if="isShow" @click="refreshPage">
<p>重新加载</p>
</div>
<!--</iscroll-view>-->
</div>
</template>
<script>
import pdfJS from 'pdfjs-dist'
import BScroll from 'better-scroll';
import navbar from '../../components/navbar/navbar'
export default {
props: {
// url: {
// type: String,
// required: true
// },
renderPages: {
type: Number,
default: 5
},
customScroll: {
type: Boolean,
default: false
},
offsetHeight: {
type: Number,
default: 0
},
},
data() {
return {
doc: null,
docPages: 0,
currentPage: 0,
scrollWrapHei: 0,
pageHeight: 0,
renderList: [],
show: false,
isShow:true,
notice: '',
timer: 0,
isDispaly: false,
totop: false,
scrollToTop: "",
url: ""
}
},
watch: {
url: {
immediate: true,
handler() {
this.getPDFFile()
}
},
$route:{
immediate: true,
deep: true,
handler(val,oldVal) {
console.log("to",val);
console.log("oldval",oldVal)
}
},
},
created() {
if (!this.customScroll) {
document.addEventListener('scroll', this.scroll)
}
},
mounted() {
this.scrollWrapHei = document.documentElement.clientHeight -
this.$refs.navbar.$el.clientHeight;
//
// this.url = this.getFileUrl;
this.url = this.$cookies.get("fileUrl");
console.log("url",this.url);
this.options = {
scrollY: true,
scrollX: false,
mouseWheel: true,
click: true,
taps: true
};
// let wrapper = document.querySelector('.iscrollWrap');
// let scroll = new BScroll(wrapper, options);
//
// let wrapper = document.querySelector('.scrollWrap');
// let betterScroll = new BScroll(wrapper, this.options);
// betterScroll.on("touchend",(pos)=>{
// console.log(pos)
// })
//解决@click失效,为什么会失效,因为加上better scroll导致失效,解决就是加一个配置参数
// console.log("this.$refs.navBar", this.$refs.navBar.getBoundingClientRect().height);
},
beforeDestroy() {
document.removeEventListener('scroll', this.scroll)
},
methods: {
getPDFFile () {
if (!this.url) return;
this.currentPage = 0;
pdfJS.getDocument(this.url).then(pdf => {
this.doc = pdf;
this.docPages = pdf.numPages;
this.$nextTick(() => {
this.docPages && this.scrollToPage(1)
})
})
},
scrollToPage (pageNo) {
if (this.currentPage === pageNo) return
this.currentPage = pageNo
let list = []
for (let page = pageNo - this.renderPages; page <= pageNo + this.renderPages; page++) {
list.push(page)
}
list = list.filter(page => page <= this.docPages && page >= 1)
this.$nextTick(() => {
this.renderList = list
this.renderList.forEach(page => {
this.renderPage(page)
})
})
},
// 渲染page
renderPage (pageNo) {
this.doc.getPage(pageNo).then(page => {
let container = this.$refs.container[pageNo - 1]
if (!container) return
let canvas = container.querySelector('canvas')
if (!canvas || canvas.__rendered) return
let ctx = canvas.getContext('2d')
let dpr = window.devicePixelRatio || 1
let bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1
let ratio = dpr / bsr
let rect = container.getBoundingClientRect()
let viewport = page.getViewport(1)
let width = rect.width
let height = width / viewport.width * viewport.height
canvas.style.width = `${width}px`
canvas.style.height = `${height}px`
this.pageHeight = height
canvas.height = height * ratio
canvas.width = width * ratio
ctx.setTransform(ratio, 0, 0, ratio, 0, 0)
page.render({
canvasContext: ctx,
viewport: page.getViewport(width/viewport.width)
})
canvas.__rendered = true
})
},
scroll () {
this.checkRender(document.documentElement)
},
checkRender (el) {
if (!this.pageHeight) return;
let scrollTop = el.scrollTop;
if(scrollTop > 300){
this.show = true;
this.isShow = false;
}else{
this.show = false;
this.isShow = true;
}
if (el === document.documentElement) {
scrollTop = el.scrollTop || window.pageYOffset || document.body.scrollTop
}
let page = Math.floor((scrollTop - this.offsetHeight) / this.pageHeight)
page = Math.max(page, 1)
page = Math.min(page, this.docPages)
this.scrollToPage(page)
},
gotoTop() {
let scrolltop = document.documentElement.scrollTop || document.body.scrollTop;
document.documentElement.scrollTop = document.body.scrollTop = 0;
this.show = false;
console.log("gotoTOp");
},
refreshPage(){
this.$router.go(0);
}
},
components: {
navbar
},
computed: {
getFileUrl() {
return this.$store.getters.getFileUrl
}
}
}
</script>
<style lang="less" scoped>
.pdf-preview-container {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 999;
background-color: #fff;
height: 100%;
/*.scroll-view {*/
/*overflow: scroll;*/
/*position: fixed;*/
/*top: 0;*/
/*bottom: 0;*/
/*left: 0;*/
/*right: 0;*/
/*!*height: 600px;*!*/
/*!*height: 100%;*!*/
/*-webkit-overflow-scrolling: touch;*/
/*}*/
.iscrollWrap {
overflow: scroll;
}
.notice,refreshPage{
position: fixed;
width: 2.5rem; /* 40/16 */
height: 2.5rem;
border-radius: 1.25rem /* 20/16 */;
opacity: 0.8;
background: darkorange;
box-shadow: 0 1px 5px 0 #e0e0e0;
right: 1.125rem; /* 18/16 */
bottom: 5rem; /* 64/16 */
z-index: 1100;
-webkit-transition: opacity .5s;
transition: opacity .5s;
color: #fff;
i {
font-size: 1.5rem;
color: #e2294c;
margin: 0 0 0 0.5rem;
position: relative;
top: 0.5rem;
}
p {
font-size: 0.65rem;
text-align: center;
padding: 0;
}
}
.refreshPage{
position: fixed;
width: 2.5rem; /* 40/16 */
height: 2.5rem;
border-radius: 1.25rem /* 20/16 */;
opacity: 0.8;
background: darkorange;
box-shadow: 0 1px 5px 0 #e0e0e0;
right: 1.125rem; /* 18/16 */
top: 0.5rem; /* 64/16 */
z-index: 1100;
-webkit-transition: opacity .5s;
transition: opacity .5s;
color: #fff;
i {
font-size: 1.5rem;
color: #e2294c;
margin: 0 0 0 0.5rem;
position: relative;
top: 0.5rem;
}
p {
font-size: 0.65rem;
text-align: center;
padding: 0;
}
}
}
.active {
display: none;
}
</style>
<3> 图片上传预览
图片上传的是使用vant的van-uploader组件,不过样式是全新定义,但是这个没有图片预览功能。所以使用了vue-preview,但是这玩意使用完全不是网上说的那样了,现在完全是一个vue组件的形式来使用的了。