修改pdf文件的预览以及添加word的下载方式

main
于阔 9 months ago
parent 88a1f1f060
commit cec1bed947

@ -1,9 +1,17 @@
<template>
<div class="pdf-viewer">
<div class="fixedToolBar">
<div class="fixedToolBar">
<ElDropdown placement="bottom">
<!-- 其中包含的功能有分页页数跳转文件下载 -->
<i @click="downloadFile" class="fa fa-download cursor-pointer download" hover-color="var(--el-color-primary)"></i>
</div>
<i class="fa fa-download cursor-pointer download" hover-color="var(--el-color-primary)"></i>
<template #dropdown>
<ElDropdownMenu>
<ElDropdownItem @click="downloadFile('pdf')">PDF</ElDropdownItem>
<ElDropdownItem @click="downloadFile('word')">WORD</ElDropdownItem>
</ElDropdownMenu>
</template>
</ElDropdown>
</div>
<div class="pdf-viewer" :loading="loading">
<div class="sidebar">
<ul>
<li v-for="(page,pageIndex) in pagesInfo" :key="page.number" @click="navigateToPage(page.number)">
@ -26,7 +34,7 @@ import { ref, onMounted, onUnmounted } from 'vue';
import * as pdfjsLib from 'pdfjs-dist';
import 'pdfjs-dist/build/pdf.worker.entry';
import { useRoute } from 'vue-router';
import { ElMessage } from 'element-plus';
import { ElMessage,ElDropdown,ElDropdownMenu,ElDropdownItem } from 'element-plus';
import {queryFileFlowRepTemplateApi,exportTemplateApi} from '@/api/reporting/RepTemplate/RepTemplate';
onMounted(() => {
@ -40,6 +48,7 @@ onUnmounted(() => {
// worker
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs-dist/build/pdf.worker.entry';
let loading = ref(false);//loading
const pdfContainer = ref(null);
const pdfDocument = ref(null);
const pdfInfo = ref({});
@ -57,7 +66,7 @@ const downLoadErrorMsg = {
"1002":"预览失败,未找到文件信息",
"1003":"预览失败,请联系管理员",
}
let BlobFile = ref(null);//blob
//
const generateThumbnails = async () => {
if (!pdfDocument.value) return;
@ -147,38 +156,49 @@ const handleScroll = (event) => {
//blobfile
const TurnBlobForRender = async (data) => {
if(!data){return}
try {
const blob = new Blob([data], { type: 'application/pdf' });
const convertedFile = new File([blob], { type: 'application/pdf' });;
if(convertedFile.size == 0)return;
pdfDocument.value = await pdfjsLib.getDocument({ data: data }).promise;
await generateThumbnails();
renderAllPages();
currentPage.value = 0; //
} catch (error) {
console.error('Error loading PDF:', error);
}
const convertedFile = new File([data], { type: 'application/pdf' });
const fileReader = new FileReader();
fileReader.onload = async (e) => {
console.log(e,"文件信息");
const typedArray = new Uint8Array(e.target.result);
try {
pdfDocument.value = await pdfjsLib.getDocument({ data: typedArray }).promise;
await generateThumbnails();
renderAllPages();
currentPage.value = 0;//
let loading = ref(false);
} catch (error) {
let loading = ref(false);
console.error('Error loading PDF:', error);
}
};
fileReader.onerror = (error) => {
console.error('Error reading file:', error);
};
fileReader.readAsArrayBuffer(convertedFile);
};
//
const fetchDocFile = async () => {
let loading = ref(true);
// API DOCX ArrayBuffer
const response = await queryFileFlowRepTemplateApi(params);
const { data, headers } = response;
if(headers['status'] == 500){// WARNERROR
const code = headers['error']?headers['error'].substring(headers['error'].length-4):'1003';
console.log(code)
switch(code){
case "1001":
case "1002":
ElMessage.error(downLoadErrorMsg[code]);
break;
default:
ElMessage.error(downLoadErrorMsg['1003']);
break;
}
if(headers['status'] == 500){// WARNERROR
const code = headers['error']?headers['error'].substring(headers['error'].length-4):'1003';
console.log(code)
switch(code){
case "1001":
case "1002":
ElMessage.error(downLoadErrorMsg[code]);
break;
default:
ElMessage.error(downLoadErrorMsg['1003']);
break;
}
let loading = ref(false);
return;
}
// const file = await new File([data], 'document.pdf', { type: data.type });
BlobFile.value = response;
TurnBlobForRender(data);
};
fetchDocFile();//blob
@ -197,6 +217,7 @@ const handleFileChange = async (event) => {
}
const fileReader = new FileReader();
fileReader.onload = async (e) => {
console.log(e,"文件信息");
const typedArray = new Uint8Array(e.target.result);
try {
pdfDocument.value = await pdfjsLib.getDocument({ data: typedArray }).promise;
@ -214,6 +235,30 @@ const handleFileChange = async (event) => {
}
};
//
const downloadFile = (type) => {
switch (type) {
case 'pdf':
const { data, headers } = BlobFile.value;
const fileName = headers['content-disposition']?.replace(/\w+;\s*filename=(.*)/, '$1');
const blob = new Blob([data], {
type: headers['content-type']
})
const dom = document.createElement('a');
const _url = window.URL.createObjectURL(blob);
dom.href = _url;
dom.download = decodeURI(fileName);
dom.style.display = 'none';
document.body.appendChild(dom);
dom.click();
dom.parentNode.removeChild(dom);
window.URL.revokeObjectURL(_url);
break;
case 'word':
exportTemplateApi({pId:params});
break;
}
};
</script>
@ -221,26 +266,28 @@ const handleFileChange = async (event) => {
<style scoped>
.pdf-viewer {
display: flex;
height: 100vh;
height: calc(100vh - 50px);
background-color: rgba(0, 0, 0, 0.7);
padding-top:70px;
padding-top:10px;
}
.fixedToolBar{
position: fixed;
/* position: fixed;
top: 0;
left: 0;
left: 0; */
width:100%;
height:50px;
line-height:50px;
background-color: #635f5f;
color:#fff;
z-index:999;
/* z-index:999; */
}
.download{
position: absolute;
position: fixed;
color:#fff;
font-size:1.3rem;
top:13px;
right:15px;
z-index:1000;
}
.sidebar {
width: 250px;

@ -73,7 +73,7 @@ export default {
case "1002":
ElMessage.error(downLoadErrorMsg[code]);
break;
case 'default':
default:
ElMessage.error(downLoadErrorMsg['1003']);
break;
}

@ -0,0 +1,105 @@
<script setup lang="tsx">
import { Form, FormSchema } from '@/components/Form'
import { useForm } from '@/hooks/web/useForm'
import { PropType,ref,reactive, watch } from 'vue'
import { useValidator } from '@/hooks/web/useValidator'
import { ElDialog } from 'element-plus';
import {vue3CronPlus} from '@/views/vue3-cron-plus/index'
const { required } = useValidator()
const props = defineProps({
currentRow: {
type: Object as PropType<any>,
default: () => null
}
})
let showCron = ref(false);
let NewCornData = "";//corn
const formSchema = reactive<FormSchema[]>([
{
field: 'cron',
label: '定时器信息',
component: 'Input',
colProps: {
span: 24
},
componentProps:{
value:"",
on:{
click:()=>{
NewCornData = formSchema[0].value;
showCron.value = true;
}
}
}
},
])
const rules = reactive({
cron:[required()],
})
const { formRegister, formMethods } = useForm()
const { setValues,getFormData, getElFormExpose } = formMethods
const submit = async () => {
const elForm = await getElFormExpose()
const valid = await elForm?.validate().catch((err) => {
console.log(err)
})
if (valid) {
const formData = await getFormData();
formData.cron = formSchema[0].value;
return formData
}
}
watch(
() => props.currentRow,
(currentRow) => {
if (!currentRow) return
setValues(currentRow)
},
{
deep: true,
immediate: true
}
)
//
const changeCron = (corn)=>{
formSchema[0].value = corn.toString();
formSchema[0].componentProps.value = corn.toString();
if(formSchema[0].value != '[object Event]'){
NewCornData = formSchema[0].value
}
}
const closeDialog = ()=>{
if(NewCornData != formSchema[0].value){
formSchema[0].value = NewCornData;
formSchema[0].componentProps.value = NewCornData;
}
showCron.value = false;
}
defineExpose({
submit
})
</script>
<template>
<Form :rules="rules" @register="formRegister" :schema="formSchema" />
<ElDialog v-model="showCron">
<vue3CronPlus
i18n="cn"
@change="changeCron"
@close="closeDialog"
max-height="300px"
/>
</ElDialog>
</template>
<style scoped>
.vue3-cron-plus-container>>>.language{
top:40px !important;
}
</style>

@ -0,0 +1,105 @@
<script setup lang="tsx">
import { Form, FormSchema } from '@/components/Form'
import { useForm } from '@/hooks/web/useForm'
import { PropType,ref,reactive, watch } from 'vue'
import { useValidator } from '@/hooks/web/useValidator'
import { ElDialog } from 'element-plus';
import {vue3CronPlus} from '@/views/vue3-cron-plus/index'
const { required } = useValidator()
const props = defineProps({
currentRow: {
type: Object as PropType<any>,
default: () => null
}
})
let showCron = ref(false);
let NewCornData = "";//corn
const formSchema = reactive<FormSchema[]>([
{
field: 'cron',
label: '定时器信息',
component: 'Input',
colProps: {
span: 24
},
componentProps:{
value:"",
on:{
click:()=>{
NewCornData = formSchema[0].value;
showCron.value = true;
}
}
}
},
])
const rules = reactive({
cron:[required()],
})
const { formRegister, formMethods } = useForm()
const { setValues,getFormData, getElFormExpose } = formMethods
const submit = async () => {
const elForm = await getElFormExpose()
const valid = await elForm?.validate().catch((err) => {
console.log(err)
})
if (valid) {
const formData = await getFormData();
formData.cron = formSchema[0].value;
return formData
}
}
watch(
() => props.currentRow,
(currentRow) => {
if (!currentRow) return
setValues(currentRow)
},
{
deep: true,
immediate: true
}
)
//
const changeCron = (corn)=>{
formSchema[0].value = corn.toString();
formSchema[0].componentProps.value = corn.toString();
if(formSchema[0].value != '[object Event]'){
NewCornData = formSchema[0].value
}
}
const closeDialog = ()=>{
if(NewCornData != formSchema[0].value){
formSchema[0].value = NewCornData;
formSchema[0].componentProps.value = NewCornData;
}
showCron.value = false;
}
defineExpose({
submit
})
</script>
<template>
<Form :rules="rules" @register="formRegister" :schema="formSchema" />
<ElDialog v-model="showCron">
<vue3CronPlus
i18n="cn"
@change="changeCron"
@close="closeDialog"
max-height="300px"
/>
</ElDialog>
</template>
<style scoped>
.vue3-cron-plus-container>>>.language{
top:40px !important;
}
</style>

@ -0,0 +1,65 @@
<script setup lang="tsx">
import { ElContainer,ElTreeSelect,ElTree } from 'element-plus';
import { ref, reactive, toRefs, watch, onMounted, nextTick } from 'vue';
let databaseList = reactive([]);//
let database = ref("");//
let datatable = reactive([]);//
let datatableList = reactive([]);
const datatableProps = {
children: 'children',
label: 'label',
}
//
const filterDataTableList = (value: string, data: Tree) => {
if (!value) return true
return data.label.includes(value)
}
</script>
<template>
<!-- 左侧选择数据库表 -->
<!-- 右侧显示筛选信息什么的信息 -->
<div class="common-layout">
<ElContainer>
<ElAside width="250px" height="100%">
<ElTabs type="border-card">
<ElTabPane label="数据表" name="dataTable">
<ElTreeSelect
v-model="database"
:data="databaseList"
placeholder="请选择数据库"
filterable
style="width: 230px"
/>
<ElTree
ref="treeRef"
style="max-width: 230px"
class="filter-tree"
:data="datatableList"
:props="datatableProps"
default-expand-all
:filter-node-method="filterDataTableList"
/>
</ElTabPane>
<ElTabPane label="指标加工规则" name="IndexProcessRule" />
</ElTabs>
</ElAside>
<ElMain>
<ElTabs tab-position="right">
<ElTabPane label="查询结构图" name="struTreePane" />
<ElTabPane label="过滤条件" name="filterPane" />
</ElTabs>
<ElDivider>关联关系</ElDivider>
</ElMain>
</ElContainer>
</div>
</template>
<style scoped>
.vue3-cron-plus-container>>>.language{
top:40px !important;
}
</style>

@ -0,0 +1,42 @@
<!-- 关联关系 -->
<script setup lang="tsx">
import { PropType,ref,reactive, watch } from 'vue'
import { useValidator } from '@/hooks/web/useValidator'
import { ElForm,ElFormItem, ElRadioGroup,ElRadio } from 'element-plus'
const { required } = useValidator()
const props = defineProps({
currentRow: {
type: Object as PropType<any>,
default: () => null
}
})
const rules = reactive({
})
let structerRelation = reactive({
parentTable: '',//
relationship: 'LEFT',//
})
</script>
<template>
<ElForm :model="structerRelation" label-width="auto" style="max-width: 600px">
<ElFormItem label="主表">
<ElInput v-model="structerRelation.parentTable" />
</ElFormItem>
<ElFormItem label="关联关系">
<ElRadioGroup v-model="structerRelation.relationship">
<ElRadio value="LEFT">左关联</ElRadio>
<ElRadio value="INNER">等值关联</ElRadio>
</ElRadioGroup>
</ElFormItem>
</ElForm>
</template>
<style scoped>
</style>

@ -0,0 +1,105 @@
<script setup lang="tsx">
import { Form, FormSchema } from '@/components/Form'
import { useForm } from '@/hooks/web/useForm'
import { PropType,ref,reactive, watch } from 'vue'
import { useValidator } from '@/hooks/web/useValidator'
import { ElDialog } from 'element-plus';
import {vue3CronPlus} from '@/views/vue3-cron-plus/index'
const { required } = useValidator()
const props = defineProps({
currentRow: {
type: Object as PropType<any>,
default: () => null
}
})
let showCron = ref(false);
let NewCornData = "";//corn
const formSchema = reactive<FormSchema[]>([
{
field: 'cron',
label: '定时器信息',
component: 'Input',
colProps: {
span: 24
},
componentProps:{
value:"",
on:{
click:()=>{
NewCornData = formSchema[0].value;
showCron.value = true;
}
}
}
},
])
const rules = reactive({
cron:[required()],
})
const { formRegister, formMethods } = useForm()
const { setValues,getFormData, getElFormExpose } = formMethods
const submit = async () => {
const elForm = await getElFormExpose()
const valid = await elForm?.validate().catch((err) => {
console.log(err)
})
if (valid) {
const formData = await getFormData();
formData.cron = formSchema[0].value;
return formData
}
}
watch(
() => props.currentRow,
(currentRow) => {
if (!currentRow) return
setValues(currentRow)
},
{
deep: true,
immediate: true
}
)
//
const changeCron = (corn)=>{
formSchema[0].value = corn.toString();
formSchema[0].componentProps.value = corn.toString();
if(formSchema[0].value != '[object Event]'){
NewCornData = formSchema[0].value
}
}
const closeDialog = ()=>{
if(NewCornData != formSchema[0].value){
formSchema[0].value = NewCornData;
formSchema[0].componentProps.value = NewCornData;
}
showCron.value = false;
}
defineExpose({
submit
})
</script>
<template>
<Form :rules="rules" @register="formRegister" :schema="formSchema" />
<ElDialog v-model="showCron">
<vue3CronPlus
i18n="cn"
@change="changeCron"
@close="closeDialog"
max-height="300px"
/>
</ElDialog>
</template>
<style scoped>
.vue3-cron-plus-container>>>.language{
top:40px !important;
}
</style>

@ -0,0 +1,137 @@
<!-- 参数配置界面 -->
<script setup lang="tsx">
import { Form, FormSchema } from '@/components/Form'
import { useForm } from '@/hooks/web/useForm'
import { PropType,ref,reactive, watch,unref } from 'vue'
import { useValidator } from '@/hooks/web/useValidator'
const { required } = useValidator()
const props = defineProps({
currentRow: {
type: Object as PropType<any>,
default: () => null
}
})
const tableColumns = reactive<ElTableColumn[]>([
{
field: 'selection',
type: 'selection',
width: 50,
},
{
field: 'index',
label: '序号',
fixed:"left",
width: 120,
},
{
field: 'jId',
label: '参数名称',
},
{
field: 'jId',
label: '参数注释',
},
{
field: 'jId',
label: '参数默认值',
},
{
field: 'jId',
label: '测试运行默认值',
},
{
field: 'jId',
label: '字段类型'
}
])
const formSchema = reactive<FormSchema[]>([
])
const rules = reactive({
})
const { formRegister, formMethods } = useForm()
const { setValues,getFormData, getElFormExpose } = formMethods
watch(
() => props.currentRow,
(currentRow) => {
if (!currentRow) return
setValues(currentRow)
},
{
deep: true,
immediate: true
}
)
let searchParam = reactive({
paramsType:"",//
searchText:"",//
})
let filterList = reactive([]);//
//
const onSelectionChange = (ids)=>{
}
//
const handleAddParams = ()=>{
}
</script>
<template>
<ElContainer>
<ElContainer>
<ElHeader>
<ElButton type="success" @click="handleAddParams"></ElButton>
<ElButton type="danger">批量删除</ElButton>
<ElInput
v-model="searchParam.searchText"
placeholder="按参数名称或注释搜索"
clearable
>
<template #prepend>
<el-select v-model="searchParam.paramsType" placeholder="Select" style="width: 115px">
<el-option label="参数名称" value="code" />
<el-option label="参数注释" value="name" />
</el-select>
</template>
</ElInput>
</ElHeader>
<ElMain>
<!-- 参数配置字段信息的表格 -->
<ElTable
align="center"
headerAlign="center"
:data="filterList"
@selection-change="onSelectionChange"
style="width:100%;"
height="calc(100% - 50px)"
>
<ElTableColumn fixed type="selection" width="55" />
<ElTableColumn width="{60}" fixed label="序号" align="center" />
<ElTableColumn prop="filedName" label="参数名称" />
<ElTableColumn prop="label" label="参数注释" />
<ElTableColumn prop="defaultVal" label="参数默认值" />
<ElTableColumn prop="testVal" label="测试运行默认值" />
<ElTableColumn prop="fieldType" label="字段类型" />
</ElTable>
</ElMain>
</ElContainer>
<ElAside width="200px">
<Form :rules="rules" @register="formRegister" :schema="formSchema" />
</ElAside>
</ElContainer>
</template>
<style scoped>
.vue3-cron-plus-container>>>.language{
top:40px !important;
}
</style>
Loading…
Cancel
Save