更新记录

1.0.0(2025-12-09)

1.0.0首次发布


平台兼容性

uni-app(4.85)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- - -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - -

tsw-file-uts PDF预览器

模块介绍

tsw-file-uts 是一个基于UTS(Universal TypeScript)开发的跨平台PDF预览模块,支持在uni-app中实现Android、iOS和HarmonyOS平台的PDF文件预览功能。

支持平台

  • Android:应用内原生预览
  • iOS:应用内原生预览
  • HarmonyOS:应用内原生预览

核心功能

应用内原生预览

通过previewPdfInApp方法,在应用内部实现PDF文件的原生预览,支持在线PDF和本地PDF文件。

API 文档

1. 应用内原生预览PDF

previewPdfInApp(pdfUrl: string): boolean

参数说明:

  • pdfUrl:PDF文件的URL(支持在线PDF)或本地文件路径

返回值:

  • boolean:是否成功启动预览

平台支持:

  • Android:✅ 支持(直接使用在线URL)
  • iOS:✅ 支持(自动下载在线PDF到本地后预览)
  • HarmonyOS:✅ 支持(仅作为兼容接口,实际使用embed组件)

2. Embed组件(鸿蒙原生PDF预览组件)

<embed tag="pdfviewer" :options='options' @pagechange="pageChange"/>

属性说明:

  • tag:固定为"pdfviewer"
  • options:配置选项
    • filePath:PDF文件的本地路径

事件说明:

  • @pagechange:页面变化事件
    • detail.type:事件类型
    • pageTotal:总页数变化
    • pageChange:当前页码变化
    • detail.pageCount:页码或总页数

平台支持:

  • Android:✅ 支持
  • iOS:✅ 支持
  • HarmonyOS:✅ 支持

3. 清理临时文件

cleanupTempFile(filePath?: string): void

参数说明:

  • filePath:临时文件路径(可选)

平台支持:

  • Android:✅ 支持
  • iOS:✅ 支持
  • HarmonyOS:✅ 支持

使用示例

基本使用(推荐方式)

<template>
    <view class="container">
        <view class="content">
            <view class="menu-item">
                <text class="menu-title">预览pdf (本app内)</text>
                <button class="btn" @click="previewPdfInApp">应用内预览 (原生)</button>
            </view>

            <!-- #ifdef APP-HARMONY -->
            <!-- 鸿蒙的代码 -->
            <view class="" style=" position: fixed; top: 0;left: 0;width: 100vw;height: 90vh;"
                v-if="pdfUrl">
                <view class="" @click.stop="pdfUrl=''">
                    返回
                </view>
                <embed class="pdf-container" tag="pdfviewer" :options='options' @pagechange="pageChange" />
            </view>
            <!-- #endif -->
        </view>
    </view>
</template>

<script>
    // #ifdef APP-HARMONY
    import '@/uni_modules/tsw-file-uts';
    // #endif
    // #ifdef APP-PLUS
    import * as pdfUts from "@/uni_modules/tsw-file-uts";
    // #endif
    export default {
        data() {
            return {
                pdf: "https://file.cqsiera.com/app/20251204/f0bc9613e4e525f837d5ba2c7b71082b.pdf",
                showPdfViewer: false,
                pdfUrl: '',
                options: {
                    filePath: '',
                },
                pageCount: 0
            }
        },
        onLoad() {
            console.log('欢迎使用预览pdf插件演示');
        },

        methods: {
            previewPdfInApp() {
                // #ifdef APP-HARMONY
                // 鸿蒙平台需要先下载PDF文件
                this.downloadPdf();
                // #endif

                // #ifdef APP-PLUS
                // 直接调用UTS插件的预览函数
                const success = pdfUts.previewPdfInApp(this.pdf);
                if (success) {
                    console.log('PDF预览请求已发送');
                } else {
                    uni.showToast({
                        title: '预览失败,请重试',
                        icon: 'none'
                    });
                }
                // #endif

            },
            // 下载PDF文件
            downloadPdf() {
                // 注意:在HarmonyOS中,需要先将远程PDF下载到本地,然后使用本地路径
                // 这里仅作为示例,实际使用时需要先下载文件
                uni.downloadFile({
                    url: 'https://file.cqsiera.com/app/20251204/f0bc9613e4e525f837d5ba2c7b71082b.pdf',
                    success: (res) => {
                        if (res.statusCode === 200) {
                            this.options.filePath = res.tempFilePath;
                            this.pdfUrl = this.options.filePath;
                        } else {
                            uni.showToast({
                                title: 'PDF下载失败',
                                icon: 'none'
                            });
                        }
                    },
                    fail: (err) => {
                        console.error('PDF下载失败:', err);
                        uni.showToast({
                            title: 'PDF下载失败',
                            icon: 'none'
                        });
                    },
                    complete: () => {
                        uni.hideLoading();
                    }
                });
            },
            //页数变化
            pageChange(e) {
                if (e.detail.type == "pageTotal") {
                    console.log('PDF总页码:', e.detail.pageCount);
                }
                if (e.detail.type == "pageChange") {
                    console.log('PDF当前页码:', e.detail.pageCount);
                }
                // this.pageCount = e.detail;
            }
        }
    }
</script>

<style>
    .container {
        flex: 1;
        background-color: #f5f5f5;
        padding: 40rpx;
        min-height: 100vh;
    }

    .header {
        margin-bottom: 60rpx;
        text-align: center;
        padding: 40rpx 20rpx;
    }

    .title {
        font-size: 40rpx;
        font-weight: bold;
        color: #333;
    }

    .content {
        width: 100%;
    }

    .menu-item {
        background-color: #fff;
        border-radius: 15rpx;
        padding: 40rpx;
        margin-bottom: 30rpx;
        box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
        transition: transform 0.2s;
    }

    .menu-item:active {
        transform: scale(0.98);
    }

    .menu-title {
        display: block;
        font-size: 34rpx;
        font-weight: bold;
        color: #333;
        margin-bottom: 15rpx;
    }

    .menu-desc {
        display: block;
        font-size: 26rpx;
        color: #666;
        margin-bottom: 30rpx;
        line-height: 1.6;
    }

    .btn {
        display: block;
        width: 100%;
        height: 88rpx;
        line-height: 88rpx;
        background-color: #007AFF;
        color: #fff;
        border-radius: 10rpx;
        text-align: center;
        font-size: 30rpx;
        border: none;
        font-weight: 500;
    }

    .btn:active {
        background-color: #0062CC;
    }

    .menu-item {
        margin-bottom: 40rpx;
        padding: 20rpx;
        background-color: #fff;
        border-radius: 10rpx;
        box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
    }

    /* PDF预览区域样式 */
    .pdf-viewer-container {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: rgba(0, 0, 0, 0.9);
        z-index: 999;
        display: flex;
        flex-direction: column;
    }

    .pdf-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 20rpx;
        background-color: #333;
        color: #fff;
    }

    .pdf-title {
        font-size: 32rpx;
        font-weight: bold;
    }

    .pdf-viewer {
        flex: 1;
        width: 100%;
    }

    .pdf-container {
        width: 100%;
        height: 100%;
    }
</style>

平台差异说明

Android平台

  1. 应用内预览:使用自定义的PDFPreviewActivity实现
  2. 在线PDF支持:支持直接使用在线URL进行预览(无需先下载)
  3. 本地PDF支持:支持本地文件路径

iOS平台

  1. 应用内预览:使用系统的PDFKit实现,支持上下/左右滑动切换、页码显示
  2. 在线PDF支持:自动下载远程PDF到本地,然后使用本地路径进行预览
  3. 临时文件管理:自动处理临时文件的创建和清理
  4. 滑动模式:支持上下/左右滑动模式切换

HarmonyOS平台

  1. 应用内预览:使用系统的PdfView组件实现
  2. 在线PDF支持:需要先将远程PDF下载到本地,然后使用本地路径进行预览
  3. 事件支持:支持页码变化事件监听

注意事项

  1. 在线PDF处理

    • Android:直接支持在线URL预览
    • iOS:自动下载在线PDF到本地后预览
    • ⚠️ HarmonyOS:需要手动下载在线PDF到本地后预览
  2. 性能优化

    • 对于大文件PDF,建议添加下载进度提示
    • 远程PDF文件预览可能受网络速度影响
  3. 兼容性

    • 确保HBuilderX版本≥3.6.8
    • Android平台需要Android 5.0+(API 21+)
    • iOS平台需要iOS 11.0+
    • HarmonyOS平台需要API 7+

常见问题

Q: 为什么HarmonyOS平台无法直接预览在线PDF?

A: HarmonyOS平台的PdfView组件需要使用本地文件路径,因此需要先将远程PDF下载到本地再进行预览。

Q: 如何获取PDF的总页数?

A: 通过监听@pagechange事件,当e.detail.type === "pageTotal"时,e.detail.pageCount即为总页数。

Q: iOS平台的滑动模式如何切换?

A: iOS平台的PDF预览控制器提供了滑动模式切换按钮,可以在上下滑动和左右滑动之间切换。

更新日志

v1.0.0

  • 初始版本发布
  • 支持Android、iOS、HarmonyOS平台
  • 提供应用内原生PDF预览功能
  • 支持在线和本地PDF文件

联系方式


许可证

MIT License

隐私、权限声明

1. 本插件需要申请的系统权限列表:

<uses-permission android:name="android.permission.INTERNET"/>

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率: