244 lines
5.9 KiB
Vue
244 lines
5.9 KiB
Vue
<script setup>
|
|
import { ref, onMounted, watch } from "vue"
|
|
import { VPdfViewer, useLicense } from "@vue-pdf-viewer/viewer"
|
|
|
|
const props = defineProps({
|
|
// Beispiel: "FEDEO/26/filesbyid/11990345-8711-4e23-8851-c50f028fc915/RE25-1081.pdf"
|
|
fileId: {
|
|
type: String,
|
|
},
|
|
uri: {
|
|
type: String,
|
|
},
|
|
scale: {
|
|
type: Number,
|
|
default: 1.2,
|
|
},
|
|
location: {
|
|
type: String,
|
|
|
|
},
|
|
noControls: {
|
|
type: Boolean,
|
|
default: false,
|
|
}
|
|
})
|
|
|
|
|
|
const config = useRuntimeConfig()
|
|
useLicense(config.public.pdfLicense)
|
|
|
|
const tempStore = useTempStore()
|
|
|
|
const pdfSrc = ref(null) // ObjectURL fürs Viewer
|
|
const { $api } = useNuxtApp()
|
|
|
|
async function loadPdf(id) {
|
|
try {
|
|
const arrayBuffer = await $api(`/api/files/download/${id}`, {
|
|
method: "POST",
|
|
responseType: "arrayBuffer", // wichtig für pdf.js
|
|
})
|
|
const blob = new Blob([arrayBuffer], { type: "application/pdf" })
|
|
pdfSrc.value = URL.createObjectURL(blob)
|
|
} catch (err) {
|
|
console.error("Fehler beim Laden der PDF:", err)
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
if(props.fileId) {
|
|
loadPdf(props.fileId)
|
|
} else if(props.uri) {
|
|
pdfSrc.value = props.uri
|
|
}
|
|
|
|
//window.addEventListener("resize", handleZoomTool("pageWidth"), true);
|
|
|
|
})
|
|
watch(() => props.fileId, (newPath) => {
|
|
if (newPath) loadPdf(newPath)
|
|
})
|
|
|
|
const vpvRef = ref(null);
|
|
|
|
//Zoom Control
|
|
|
|
const zoomControl = computed(() => vpvRef.value?.zoomControl)
|
|
|
|
const currentScale = computed(() => {
|
|
return zoomControl.value?.scale
|
|
})
|
|
|
|
const handleZoomTool = (type, rawScale) => {
|
|
console.log(type)
|
|
const zoomCtrl = unref(zoomControl)
|
|
if (!zoomCtrl) return
|
|
|
|
const scale = unref(currentScale)
|
|
if(!type ){
|
|
zoomCtrl.zoom(rawScale)
|
|
} else if (type === "in") {
|
|
scale && zoomCtrl.zoom(scale + 0.25)
|
|
} else if (type === "out") {
|
|
scale && zoomCtrl.zoom(scale - 0.25)
|
|
} else {
|
|
zoomCtrl.zoom(type)
|
|
}
|
|
|
|
if(["in","out"].includes(type)){
|
|
tempStore.modifySettings(`pdfviewer-scale-${props.location}`,scale)
|
|
}
|
|
|
|
}
|
|
//Page Control
|
|
const pageControl = computed(() => vpvRef.value?.pageControl)
|
|
const currentPageInput = computed(() => pageControl.value?.currentPage)
|
|
const searchControl = computed(() => vpvRef.value?.searchControl)
|
|
const totalMatches = computed(() => searchControl.value?.searchMatches?.totalMatches)
|
|
|
|
const isNextPageButtonDisable = computed(() =>
|
|
pageControl.value?.currentPage === pageControl.value?.totalPages
|
|
)
|
|
|
|
const isPreviousPageButtonDisable = computed(() =>
|
|
pageControl.value?.currentPage === 1
|
|
)
|
|
|
|
const prevPage = () => {
|
|
const isFirstPage = pageControl.value?.currentPage === 1
|
|
if (isFirstPage) return
|
|
pageControl.value?.goToPage(pageControl.value?.currentPage - 1)
|
|
}
|
|
|
|
const nextPage = () => {
|
|
const isLastPage = pageControl.value?.currentPage === pageControl.value?.totalPages
|
|
if (isLastPage) return
|
|
pageControl.value?.goToPage(pageControl.value?.currentPage + 1)
|
|
}
|
|
|
|
const handleKeyPress = (event) => {
|
|
if (event.key === "Enter") {
|
|
handlePageInput(event)
|
|
}
|
|
}
|
|
|
|
//Handle Download
|
|
const downloadControl = computed(() => vpvRef.value?.downloadControl)
|
|
|
|
const handleDownloadFile = async () => {
|
|
if(props.fileId){
|
|
await useFiles().downloadFile(props.fileId)
|
|
} else if(props.uri){
|
|
const a = document.createElement("a");
|
|
a.href = props.uri;
|
|
a.download = "entwurf.pdf";
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
document.body.removeChild(a);
|
|
}
|
|
|
|
|
|
|
|
/*const downloadCtrl = unref(downloadControl)
|
|
if (!downloadCtrl) return
|
|
downloadCtrl.download()*/
|
|
}
|
|
|
|
watch(downloadControl, (downloadCtrl) => {
|
|
if (!downloadCtrl) return
|
|
|
|
downloadCtrl.onError = (error) => {
|
|
console.log("Download error", error)
|
|
}
|
|
|
|
downloadCtrl.onComplete = () => {
|
|
console.log("Download completed")
|
|
}
|
|
})
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex flex-col gap-4 justify-self-center" v-if="!noControls">
|
|
<div class="flex items-center gap-4 text-[#7862FF] bg-pale-blue border-[#D7D1FB] rounded-lg p-2 justify-center">
|
|
|
|
<!-- Zoom out button -->
|
|
<UButton
|
|
@click="() => handleZoomTool('pageWidth')"
|
|
icon="i-heroicons-document-text"
|
|
variant="outline"
|
|
></UButton>
|
|
|
|
<UButton
|
|
@click="() => handleZoomTool('out')"
|
|
icon="i-heroicons-magnifying-glass-minus"
|
|
variant="outline"
|
|
></UButton>
|
|
|
|
<!-- Zoom in button -->
|
|
<UButton
|
|
@click="() => handleZoomTool('in')"
|
|
icon="i-heroicons-magnifying-glass-plus"
|
|
variant="outline"
|
|
></UButton>
|
|
<UButton
|
|
v-if="props.fileId || props.uri"
|
|
@click="handleDownloadFile"
|
|
variant="outline"
|
|
icon="i-heroicons-arrow-down-on-square"
|
|
/>
|
|
<UButton
|
|
@click="prevPage"
|
|
:disabled="isPreviousPageButtonDisable"
|
|
icon="i-heroicons-chevron-up"
|
|
variant="outline"
|
|
></UButton>
|
|
|
|
|
|
|
|
<!-- Page number input and total pages display -->
|
|
<div class="flex items-center text-sm font-normal">
|
|
<UInput
|
|
v-model="currentPageInput"
|
|
class="w-24 h-8 rounded-sm focus:outline-none"
|
|
@change="handleKeyPress"
|
|
>
|
|
<template #trailing>
|
|
/ {{ pageControl?.totalPages }}
|
|
</template>
|
|
</UInput>
|
|
</div>
|
|
|
|
<!-- Next page button -->
|
|
<UButton
|
|
@click="nextPage"
|
|
:disabled="isNextPageButtonDisable"
|
|
icon="i-heroicons-chevron-down"
|
|
variant="outline"
|
|
></UButton>
|
|
</div>
|
|
</div>
|
|
<div class="pdf-container">
|
|
<VPdfViewer
|
|
v-if="pdfSrc"
|
|
:src="pdfSrc"
|
|
style="height: 78vh; width: 100%;"
|
|
:toolbar-options="false"
|
|
ref="vpvRef"
|
|
@loaded="handleZoomTool(null,tempStore.settings[`pdfviewer-scale-${props.location}`] || 1)"
|
|
/>
|
|
<div v-else>
|
|
<UProgress
|
|
class="mt-5 w-2/3 mx-auto"
|
|
animation="carousel"></UProgress>
|
|
</div>
|
|
</div></template>
|
|
|
|
<style scoped>
|
|
.pdf-container {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
</style>
|