mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-09-19 10:06:38 +08:00
feat(projects): add plugin pdf preview (#568)
This commit is contained in:
parent
24320ab899
commit
a9dce21878
@ -74,6 +74,7 @@
|
|||||||
"vue": "3.4.33",
|
"vue": "3.4.33",
|
||||||
"vue-draggable-plus": "0.5.2",
|
"vue-draggable-plus": "0.5.2",
|
||||||
"vue-i18n": "9.13.1",
|
"vue-i18n": "9.13.1",
|
||||||
|
"vue-pdf-embed": "2.1.0",
|
||||||
"vue-router": "4.4.0",
|
"vue-router": "4.4.0",
|
||||||
"wangeditor": "4.7.15",
|
"wangeditor": "4.7.15",
|
||||||
"xgplayer": "3.0.19",
|
"xgplayer": "3.0.19",
|
||||||
|
@ -199,7 +199,8 @@ const local: App.I18n.Schema = {
|
|||||||
plugin_video: 'Video',
|
plugin_video: 'Video',
|
||||||
plugin_barcode: 'Barcode',
|
plugin_barcode: 'Barcode',
|
||||||
plugin_pinyin: 'pinyin',
|
plugin_pinyin: 'pinyin',
|
||||||
plugin_excel: 'Excel'
|
plugin_excel: 'Excel',
|
||||||
|
plugin_pdf: 'PDF preview'
|
||||||
},
|
},
|
||||||
page: {
|
page: {
|
||||||
login: {
|
login: {
|
||||||
|
@ -199,7 +199,8 @@ const local: App.I18n.Schema = {
|
|||||||
plugin_video: '视频',
|
plugin_video: '视频',
|
||||||
plugin_barcode: '条形码',
|
plugin_barcode: '条形码',
|
||||||
plugin_pinyin: '拼音',
|
plugin_pinyin: '拼音',
|
||||||
plugin_excel: 'Excel'
|
plugin_excel: 'Excel',
|
||||||
|
plugin_pdf: 'PDF 预览'
|
||||||
},
|
},
|
||||||
page: {
|
page: {
|
||||||
login: {
|
login: {
|
||||||
|
@ -44,6 +44,7 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
|
|||||||
plugin_excel: () => import("@/views/plugin/excel/index.vue"),
|
plugin_excel: () => import("@/views/plugin/excel/index.vue"),
|
||||||
plugin_icon: () => import("@/views/plugin/icon/index.vue"),
|
plugin_icon: () => import("@/views/plugin/icon/index.vue"),
|
||||||
plugin_map: () => import("@/views/plugin/map/index.vue"),
|
plugin_map: () => import("@/views/plugin/map/index.vue"),
|
||||||
|
plugin_pdf: () => import("@/views/plugin/pdf/index.vue"),
|
||||||
plugin_pinyin: () => import("@/views/plugin/pinyin/index.vue"),
|
plugin_pinyin: () => import("@/views/plugin/pinyin/index.vue"),
|
||||||
plugin_print: () => import("@/views/plugin/print/index.vue"),
|
plugin_print: () => import("@/views/plugin/print/index.vue"),
|
||||||
plugin_swiper: () => import("@/views/plugin/swiper/index.vue"),
|
plugin_swiper: () => import("@/views/plugin/swiper/index.vue"),
|
||||||
|
@ -444,6 +444,16 @@ export const generatedRoutes: GeneratedRoute[] = [
|
|||||||
icon: 'mdi:map'
|
icon: 'mdi:map'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'plugin_pdf',
|
||||||
|
path: '/plugin/pdf',
|
||||||
|
component: 'view.plugin_pdf',
|
||||||
|
meta: {
|
||||||
|
title: 'plugin_pdf',
|
||||||
|
i18nKey: 'route.plugin_pdf',
|
||||||
|
icon:'uiw:file-pdf'
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'plugin_pinyin',
|
name: 'plugin_pinyin',
|
||||||
path: '/plugin/pinyin',
|
path: '/plugin/pinyin',
|
||||||
|
@ -212,6 +212,7 @@ const routeMap: RouteMap = {
|
|||||||
"plugin_excel": "/plugin/excel",
|
"plugin_excel": "/plugin/excel",
|
||||||
"plugin_icon": "/plugin/icon",
|
"plugin_icon": "/plugin/icon",
|
||||||
"plugin_map": "/plugin/map",
|
"plugin_map": "/plugin/map",
|
||||||
|
"plugin_pdf": "/plugin/pdf",
|
||||||
"plugin_pinyin": "/plugin/pinyin",
|
"plugin_pinyin": "/plugin/pinyin",
|
||||||
"plugin_print": "/plugin/print",
|
"plugin_print": "/plugin/print",
|
||||||
"plugin_swiper": "/plugin/swiper",
|
"plugin_swiper": "/plugin/swiper",
|
||||||
|
5
src/typings/components.d.ts
vendored
5
src/typings/components.d.ts
vendored
@ -19,6 +19,7 @@ declare module 'vue' {
|
|||||||
IconAntDesignEnterOutlined: typeof import('~icons/ant-design/enter-outlined')['default']
|
IconAntDesignEnterOutlined: typeof import('~icons/ant-design/enter-outlined')['default']
|
||||||
IconAntDesignReloadOutlined: typeof import('~icons/ant-design/reload-outlined')['default']
|
IconAntDesignReloadOutlined: typeof import('~icons/ant-design/reload-outlined')['default']
|
||||||
IconAntDesignSettingOutlined: typeof import('~icons/ant-design/setting-outlined')['default']
|
IconAntDesignSettingOutlined: typeof import('~icons/ant-design/setting-outlined')['default']
|
||||||
|
'IconCharm:download': typeof import('~icons/charm/download')['default']
|
||||||
'IconFileIcons:microsoftExcel': typeof import('~icons/file-icons/microsoft-excel')['default']
|
'IconFileIcons:microsoftExcel': typeof import('~icons/file-icons/microsoft-excel')['default']
|
||||||
IconGridiconsFullscreen: typeof import('~icons/gridicons/fullscreen')['default']
|
IconGridiconsFullscreen: typeof import('~icons/gridicons/fullscreen')['default']
|
||||||
IconGridiconsFullscreenExit: typeof import('~icons/gridicons/fullscreen-exit')['default']
|
IconGridiconsFullscreenExit: typeof import('~icons/gridicons/fullscreen-exit')['default']
|
||||||
@ -32,6 +33,8 @@ declare module 'vue' {
|
|||||||
IconLocalBanner: typeof import('~icons/local/banner')['default']
|
IconLocalBanner: typeof import('~icons/local/banner')['default']
|
||||||
IconLocalCast: typeof import('~icons/local/cast')['default']
|
IconLocalCast: typeof import('~icons/local/cast')['default']
|
||||||
IconLocalLogo: typeof import('~icons/local/logo')['default']
|
IconLocalLogo: typeof import('~icons/local/logo')['default']
|
||||||
|
'IconMaterialSymbolsLight:rotate90DegreesCcwOutlineRounded': typeof import('~icons/material-symbols-light/rotate90-degrees-ccw-outline-rounded')['default']
|
||||||
|
'IconMdi:printer': typeof import('~icons/mdi/printer')['default']
|
||||||
IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default']
|
IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default']
|
||||||
IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default']
|
IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default']
|
||||||
IconMdiDrag: typeof import('~icons/mdi/drag')['default']
|
IconMdiDrag: typeof import('~icons/mdi/drag')['default']
|
||||||
@ -77,12 +80,14 @@ declare module 'vue' {
|
|||||||
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
||||||
NModal: typeof import('naive-ui')['NModal']
|
NModal: typeof import('naive-ui')['NModal']
|
||||||
NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
|
NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
|
||||||
|
NPagination: typeof import('naive-ui')['NPagination']
|
||||||
NPopconfirm: typeof import('naive-ui')['NPopconfirm']
|
NPopconfirm: typeof import('naive-ui')['NPopconfirm']
|
||||||
NPopover: typeof import('naive-ui')['NPopover']
|
NPopover: typeof import('naive-ui')['NPopover']
|
||||||
NRadio: typeof import('naive-ui')['NRadio']
|
NRadio: typeof import('naive-ui')['NRadio']
|
||||||
NRadioGroup: typeof import('naive-ui')['NRadioGroup']
|
NRadioGroup: typeof import('naive-ui')['NRadioGroup']
|
||||||
NScrollbar: typeof import('naive-ui')['NScrollbar']
|
NScrollbar: typeof import('naive-ui')['NScrollbar']
|
||||||
NSelect: typeof import('naive-ui')['NSelect']
|
NSelect: typeof import('naive-ui')['NSelect']
|
||||||
|
NSkeleton: typeof import('naive-ui')['NSkeleton']
|
||||||
NSpace: typeof import('naive-ui')['NSpace']
|
NSpace: typeof import('naive-ui')['NSpace']
|
||||||
NStatistic: typeof import('naive-ui')['NStatistic']
|
NStatistic: typeof import('naive-ui')['NStatistic']
|
||||||
NSwitch: typeof import('naive-ui')['NSwitch']
|
NSwitch: typeof import('naive-ui')['NSwitch']
|
||||||
|
2
src/typings/elegant-router.d.ts
vendored
2
src/typings/elegant-router.d.ts
vendored
@ -68,6 +68,7 @@ declare module "@elegant-router/types" {
|
|||||||
"plugin_excel": "/plugin/excel";
|
"plugin_excel": "/plugin/excel";
|
||||||
"plugin_icon": "/plugin/icon";
|
"plugin_icon": "/plugin/icon";
|
||||||
"plugin_map": "/plugin/map";
|
"plugin_map": "/plugin/map";
|
||||||
|
"plugin_pdf": "/plugin/pdf";
|
||||||
"plugin_pinyin": "/plugin/pinyin";
|
"plugin_pinyin": "/plugin/pinyin";
|
||||||
"plugin_print": "/plugin/print";
|
"plugin_print": "/plugin/print";
|
||||||
"plugin_swiper": "/plugin/swiper";
|
"plugin_swiper": "/plugin/swiper";
|
||||||
@ -175,6 +176,7 @@ declare module "@elegant-router/types" {
|
|||||||
| "plugin_excel"
|
| "plugin_excel"
|
||||||
| "plugin_icon"
|
| "plugin_icon"
|
||||||
| "plugin_map"
|
| "plugin_map"
|
||||||
|
| "plugin_pdf"
|
||||||
| "plugin_pinyin"
|
| "plugin_pinyin"
|
||||||
| "plugin_print"
|
| "plugin_print"
|
||||||
| "plugin_swiper"
|
| "plugin_swiper"
|
||||||
|
82
src/views/plugin/pdf/index.vue
Normal file
82
src/views/plugin/pdf/index.vue
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, shallowRef } from 'vue';
|
||||||
|
import VuePdfEmbed from 'vue-pdf-embed';
|
||||||
|
import { useLoading } from '@sa/hooks';
|
||||||
|
|
||||||
|
const { loading, endLoading } = useLoading(true);
|
||||||
|
|
||||||
|
const pdfRef = shallowRef<InstanceType<typeof VuePdfEmbed> | null>(null);
|
||||||
|
const source = `https://xiaoxian521.github.io/hyperlink/pdf/Cookie%E5%92%8CSession%E5%8C%BA%E5%88%AB%E7%94%A8%E6%B3%95.pdf`;
|
||||||
|
|
||||||
|
const showAllPages = ref(false);
|
||||||
|
const currentPage = ref<undefined | number>(1);
|
||||||
|
const pageCount = ref(1);
|
||||||
|
|
||||||
|
function onPdfRendered() {
|
||||||
|
endLoading();
|
||||||
|
|
||||||
|
if (pdfRef.value?.doc) {
|
||||||
|
pageCount.value = pdfRef.value.doc.numPages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showAllPagesChange() {
|
||||||
|
currentPage.value = showAllPages.value ? undefined : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rotations = [0, 90, 180, 270];
|
||||||
|
const currentRotation = ref(0);
|
||||||
|
|
||||||
|
function handleRotate() {
|
||||||
|
currentRotation.value = (currentRotation.value + 1) % 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handlePrint() {
|
||||||
|
await pdfRef.value?.print(undefined, 'test.pdf', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleDownload() {
|
||||||
|
await pdfRef.value?.download('test.pdf');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="overflow-hidden">
|
||||||
|
<NCard title="PDF 预览" :bordered="false" class="h-full card-wrapper" content-class="overflow-hidden">
|
||||||
|
<div class="h-full flex-col-stretch">
|
||||||
|
<GithubLink link="https://github.com/hrynko/vue-pdf-embed" />
|
||||||
|
<WebSiteLink label="文档地址:" link="https://www.npmjs.com/package/vue-pdf-embed" />
|
||||||
|
<div class="flex-y-center justify-end gap-12px">
|
||||||
|
<NCheckbox v-model:checked="showAllPages" @update:checked="showAllPagesChange">显示所有页面</NCheckbox>
|
||||||
|
<ButtonIcon tooltip-content="旋转90度" @click="handleRotate">
|
||||||
|
<icon-material-symbols-light:rotate-90-degrees-ccw-outline-rounded />
|
||||||
|
</ButtonIcon>
|
||||||
|
<ButtonIcon tooltip-content="打印" @click="handlePrint">
|
||||||
|
<icon-mdi:printer />
|
||||||
|
</ButtonIcon>
|
||||||
|
<ButtonIcon tooltip-content="下载" @click="handleDownload">
|
||||||
|
<icon-charm:download />
|
||||||
|
</ButtonIcon>
|
||||||
|
</div>
|
||||||
|
<NScrollbar class="flex-1-hidden">
|
||||||
|
<NSkeleton v-if="loading" size="small" class="mt-12px" text :repeat="12" />
|
||||||
|
<VuePdfEmbed
|
||||||
|
ref="pdfRef"
|
||||||
|
class="overflow-auto container"
|
||||||
|
:class="{ 'h-0': loading }"
|
||||||
|
:rotation="rotations[currentRotation]"
|
||||||
|
:page="currentPage"
|
||||||
|
:source="source"
|
||||||
|
@rendered="onPdfRendered"
|
||||||
|
/>
|
||||||
|
</NScrollbar>
|
||||||
|
<div class="flex-y-center justify-between">
|
||||||
|
<div v-if="showAllPages" class="text-18px font-medium">共{{ pageCount }}页</div>
|
||||||
|
<NPagination v-else v-model:page="currentPage" :page-count="pageCount" :page-size="1" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</NCard>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
Loading…
Reference in New Issue
Block a user