vue-ofd-viewer
v0.0.2
Published
vue-ofd-viewer - OFD document viewer for Vue 2 and Vue 3 with customizable toolbar
Maintainers
Readme
vue-ofd-viewer
📋 项目概述
vue-ofd-viewer 是一个功能完整、高度可定制的 OFD(Open Fixed-layout Document)文档查看器组件,专为 Vue.js 应用程序设计。该组件提供了企业级的文档查看解决方案,支持 Vue 2.6+ 和 Vue 3.x 双版本,具备完整的 TypeScript 类型支持。
🏗️ 技术架构
┌─────────────────────────────────────────────────────────────┐
│ vue-ofd-viewer │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ OfdView │ │ Thumbnail │ │ Toolbar │ │
│ │ (主组件) │ │ Panel │ │ (工具栏组件) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────────┬──────────┘ │
│ │ │ │ │
│ ┌──────┴────────────────┴────────────────────┴──────────┐ │
│ │ Core Engine │ │
│ │ ┌────────────┐ ┌────────────┐ ┌────────────────┐ │ │
│ │ │ OFD Parser │ │ Renderer │ │ Signature │ │ │
│ │ │ (解析器) │ │ (渲染器) │ │ Verifier │ │ │
│ │ └────────────┘ └────────────┘ └────────────────┘ │ │
│ └───────────────────────────────────────────────────────┘ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Composables │ │
│ │ ┌────────────┐ ┌────────────┐ ┌────────────────┐ │ │
│ │ │ useConfig │ │ vue-demi │ │ Mosaic │ │ │
│ │ │ (配置管理) │ │ (兼容层) │ │ (马赛克工具) │ │ │
│ │ └────────────┘ └────────────┘ └────────────────┘ │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘🔧 技术栈
| 类别 | 技术 | |------|------| | 框架 | Vue 2.6+ / Vue 3.x (via vue-demi) | | 语言 | TypeScript 5.5+ | | 构建 | Vite 5.x | | OFD解析 | ofd-xml-parser | | 加密算法 | sm-crypto (国密算法) | | 签名验证 | jsrsasign |
✨ 特性
核心功能
- 📄 OFD 文档渲染 - 高保真渲染 OFD 文档,支持复杂排版
- 🔍 缩放控制 - 多级缩放,支持自适应、实际大小、百分比等多种模式
- 📐 缩略图面板 - 快速导航,支持打印页面选择
- 🖨️ 打印支持 - 支持全部打印、选择页面打印
- 📥 下载功能 - 一键下载 OFD 文档
- 🔐 签章验证 - 查看数字签章信息,验证文档完整性
- 🔲 马赛克工具 - 敏感信息遮罩处理
开发体验
- 🎨 高度可定制 - 工具栏按钮、样式、布局全面可配置
- 📦 开箱即用 - 零配置即可使用,所有功能默认启用
- 🔒 类型安全 - 完整的 TypeScript 类型定义
- 🌐 双版本支持 - 同时支持 Vue 2 和 Vue 3
- 📱 响应式设计 - 适配各种屏幕尺寸
📦 安装
环境要求
| 依赖 | 版本要求 | |------|---------| | Node.js | >= 16.0.0 | | Vue | ^2.6.14 或 ^3.0.0 |
安装命令
# npm
npm install vue-ofd-viewer
# yarn
yarn add vue-ofd-viewer
# pnpm
pnpm add vue-ofd-viewerVue 2 额外依赖
如果您使用 Vue 2,需要额外安装 Composition API 插件:
npm install @vue/composition-api🚀 快速开始
Vue 3 项目
1. 全局注册
// main.ts
import { createApp } from "vue";
import App from "./App.vue";
import VueOfdViewer from "vue-ofd-viewer";
import "vue-ofd-viewer/style.css";
const app = createApp(App);
app.use(VueOfdViewer);
app.mount("#app");2. 组件使用
<template>
<div class="document-container">
<OfdView
:ofdLink="documentUrl"
:config="viewerConfig"
@ready="handleReady"
@pageChange="handlePageChange"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { createOfdViewerConfig, type OfdViewerExpose } from "vue-ofd-viewer";
const documentUrl = ref("/documents/sample.ofd");
const viewerConfig = createOfdViewerConfig({
toolbar: {
buttons: {
print: { key: "print", visible: true },
download: { key: "download", visible: true },
},
defaultScale: 5, // 默认 100%
},
thumbnailPanel: {
visible: true,
width: 200,
},
});
const handleReady = (instance: OfdViewerExpose) => {
console.log("文档加载完成,共", instance.pageCount, "页");
};
const handlePageChange = (page: number) => {
console.log("当前页:", page);
};
</script>
<style scoped>
.document-container {
width: 100%;
height: 100vh;
}
</style>Vue 2 项目
1. 全局注册
// main.js
import Vue from "vue";
import VueCompositionAPI from "@vue/composition-api";
import VueOfdViewer from "vue-ofd-viewer";
import "vue-ofd-viewer/style.css";
Vue.use(VueCompositionAPI);
Vue.use(VueOfdViewer);
new Vue({
render: (h) => h(App),
}).$mount("#app");2. 组件使用
<template>
<div class="document-container">
<OfdView
:ofdLink="documentUrl"
:config="viewerConfig"
@ready="handleReady"
/>
</div>
</template>
<script>
import { createOfdViewerConfig } from "vue-ofd-viewer";
export default {
name: "DocumentViewer",
data() {
return {
documentUrl: "/documents/sample.ofd",
viewerConfig: createOfdViewerConfig({
toolbar: {
defaultScale: 5,
},
}),
};
},
methods: {
handleReady(instance) {
console.log("文档加载完成,共", instance.pageCount, "页");
},
},
};
</script>📖 API 文档
组件 Props
OfdView Props
| 属性名 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| ofdLink | string | - | OFD 文档 URL 地址 |
| showOpenFileButton | boolean | true | 是否显示打开文件按钮 |
| config | OfdViewerConfig | - | 查看器配置对象 |
| sealClick | (sealInfo: IOfdSignatureInfo) => void | - | 签章点击回调 |
配置类型定义
OfdViewerConfig
interface OfdViewerConfig {
toolbar?: ToolbarConfig | false; // 工具栏配置,false 表示隐藏
thumbnailPanel?: ThumbnailPanelConfig | false; // 缩略图面板配置
showOpenFileButton?: boolean; // 是否显示打开文件按钮
showLoading?: boolean; // 是否显示加载动画
loadingText?: string; // 加载提示文字
}ToolbarConfig
interface ToolbarConfig {
visible?: boolean; // 是否显示工具栏
buttons?: Partial<Record<ToolbarButtonKey, ToolbarButtonConfig | false>>;
scaleList?: ScaleOption[]; // 自定义缩放选项
defaultScale?: number; // 默认缩放值
}
interface ToolbarButtonConfig {
key: ToolbarButtonKey; // 按钮唯一标识
visible?: boolean; // 是否显示
title?: string; // 提示文字
order?: number; // 排序权重
}
interface ScaleOption {
value: number; // 缩放值
label: string; // 显示标签
}ThumbnailPanelConfig
interface ThumbnailPanelConfig {
visible?: boolean; // 是否显示
width?: number; // 面板宽度 (px)
position?: "left" | "right"; // 显示位置
showPageNumber?: boolean; // 是否显示页码
showPrintSelect?: boolean; // 是否显示打印选择图标
}工具栏按钮键值
| Key | 功能 | 说明 |
|-----|------|------|
| openFile | 打开文件 | 打开本地 OFD 文件 |
| firstPage | 首页 | 跳转到第一页 |
| prePage | 上一页 | 向前翻页 |
| pageInput | 页码输入 | 显示当前页码,支持跳转 |
| nextPage | 下一页 | 向后翻页 |
| lastPage | 末页 | 跳转到最后一页 |
| zoomOut | 缩小 | 缩小文档 |
| zoomSelect | 缩放选择 | 下拉选择缩放比例 |
| zoomIn | 放大 | 放大文档 |
| thumbnail | 缩略图 | 切换缩略图面板 |
| fullScreen | 全屏 | 切换全屏模式 |
| print | 打印 | 打印文档 |
| download | 下载 | 下载 OFD 文件 |
| sealInfo | 签章信息 | 查看签章详情 |
| mosaic | 马赛克 | 马赛克绘制工具 |
暴露方法
通过 ref 可以访问以下方法:
interface OfdViewerExpose {
// 页面导航
firstPage(): void;
prePage(): void;
nextPage(): void;
lastPage(): void;
gotoPage(page: number): void;
// 缩放控制
zoomIn(): Promise<void>;
zoomOut(): Promise<void>;
setScale(scale: number): Promise<void>;
// 文件操作
openFile(file: File | string): Promise<void>;
print(): void;
download(): void;
// UI 控制
toggleThumbnail(): void;
toggleFullScreen(): void;
enableMosaic(): void;
// 数据获取
readonly pageIndex: number;
readonly pageCount: number;
readonly loading: boolean;
getSeals(): ISeal[];
getPrintList(): Set<number>;
clearPrintList(): void;
}方法使用示例
<template>
<div>
<OfdView ref="ofdRef" :ofdLink="documentUrl" />
<div class="controls">
<button @click="handlePrint">打印</button>
<button @click="handleZoomIn">放大</button>
<button @click="handleGotoPage(10)">跳转到第10页</button>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import type { OfdViewerExpose } from "vue-ofd-viewer";
const ofdRef = ref<OfdViewerExpose>();
const handlePrint = () => {
ofdRef.value?.print();
};
const handleZoomIn = () => {
ofdRef.value?.zoomIn();
};
const handleGotoPage = (page: number) => {
ofdRef.value?.gotoPage(page);
};
</script>事件
| 事件名 | 参数 | 说明 |
|--------|------|------|
| ready | OfdViewerExpose | 文档加载完成 |
| pageChange | number | 页码变化 |
| scaleChange | number | 缩放比例变化 |
🎨 高级配置
自定义工具栏
const config = createOfdViewerConfig({
toolbar: {
// 隐藏特定按钮
buttons: {
print: false, // 隐藏打印按钮
download: false, // 隐藏下载按钮
mosaic: { // 自定义按钮配置
key: "mosaic",
visible: true,
title: "敏感信息遮罩",
},
},
// 自定义缩放选项
scaleList: [
{ value: 0, label: "自适应" },
{ value: 5, label: "100%" },
{ value: 7.5, label: "150%" },
{ value: 10, label: "200%" },
],
// 默认缩放比例
defaultScale: 5,
},
});自定义缩略图面板
const config = createOfdViewerConfig({
thumbnailPanel: {
visible: true,
width: 250,
position: "right",
showPageNumber: true,
showPrintSelect: true,
},
});隐藏工具栏
const config = createOfdViewerConfig({
toolbar: false, // 完全隐藏工具栏
});📁 项目结构
vue-ofd-viewer/
├── src/
│ ├── components/ # Vue 组件
│ │ ├── OfdView.vue # 主组件
│ │ ├── common/ # 通用组件
│ │ │ ├── Dialog.vue
│ │ │ ├── ThumbnailPanel.vue
│ │ │ └── FullScreenLoading.vue
│ │ └── toolbar/ # 工具栏组件
│ │ ├── ToolbarButton.vue
│ │ ├── ToolbarPage.vue
│ │ └── ToolbarZoom.vue
│ ├── composables/ # 组合式函数
│ │ └── useConfig.ts # 配置管理
│ ├── compat/ # Vue 兼容层
│ │ └── index.ts # vue-demi 封装
│ ├── core/ # 核心引擎
│ │ ├── ofd/ # OFD 解析与渲染
│ │ └── jbig2/ # 图像解码
│ ├── types/ # TypeScript 类型
│ │ ├── config.ts # 配置类型
│ │ └── ofd.ts # OFD 类型
│ ├── utils/ # 工具函数
│ │ ├── helpers.ts # 辅助函数
│ │ └── mosaic.ts # 马赛克工具
│ └── index.ts # 入口文件
├── dist/ # 构建产物
│ ├── vue-ofd-viewer.es.js # ES Module
│ ├── vue-ofd-viewer.umd.js # UMD 格式
│ ├── style.css # 样式文件
│ └── index.d.ts # 类型声明
└── package.json🔧 开发指南
本地开发
# 克隆项目
git clone https://gitee.com/usin_cc/vue-ofd-viewer.git
# 安装依赖
npm install
# 启动开发服务器
npm run dev
# 类型检查
npm run type-check
# 构建库
npm run build:lib发布流程
# 1. 更新版本号
npm version patch/minor/major
# 2. 构建
npm run build:lib
# 3. 发布
npm publish❓ 常见问题
Q1: Vue 2 项目中组件无法正常工作?
A: 确保已安装 @vue/composition-api 插件并在入口文件中注册:
import VueCompositionAPI from "@vue/composition-api";
Vue.use(VueCompositionAPI);Q2: 如何处理跨域问题?
A: OFD 文件需要通过 HTTP 服务提供,确保服务器配置了正确的 CORS 头:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GETQ3: 打印时页面显示不完整?
A: 这通常是因为文档未完全加载。请确保在 ready 事件触发后再调用打印功能。
Q4: 如何自定义按钮样式?
A: 可以通过 CSS 变量覆盖默认样式:
:root {
--ofd-toolbar-bg: #f5f5f5;
--ofd-toolbar-icon-color: #333;
--ofd-toolbar-icon-hover-color: #409eff;
}Q5: 支持 SSR 吗?
A: 当前版本不支持服务端渲染 (SSR),请在客户端渲染环境中使用。
🤝 贡献指南
我们欢迎所有形式的贡献!
贡献流程
- Fork 本仓库
- 创建特性分支 (
git checkout -b feature/AmazingFeature) - 提交更改 (
git commit -m 'Add some AmazingFeature') - 推送到分支 (
git push origin feature/AmazingFeature) - 提交 Pull Request
代码规范
- 使用 TypeScript 编写代码
- 遵循 ESLint 规则
- 编写单元测试
- 更新相关文档
📄 许可证
本项目基于 MIT 许可证开源。
📞 联系方式
- 作者: Usin
- 邮箱: [email protected]
- 问题反馈: Gitee Issues
