TextIn OCR Frontend前端开源组件库发布!
为什么开源 TextIn OCR Frontend 前端组件库?
在 TextIn 社群中,我们时常接到用户反馈,调取 API 进行票据等文件批量识别后,需要另行完成前端工程,实现比对环节。为助力用户节省工程成本,TextIn 团队正式开源 OCR Frontend 前端组件库,便于用户搭建前端界面,完成识别结果审核,提升使用体验。
此外,对于有翻译、校对等需求的开发者,也可灵活应用开源组件库,进行二次开发。
TextIn OCR Frontend 是一个用于展示 Textin 识别结果的 React 组件库,支持文件预览、坐标回显和结果展示。
组件库适配票据类解析结果(key-value)的展示,前端界面案例见下图。
特性
-
📄 支持图片和 PDF 文件预览
-
🎯 支持文本区域坐标回显和高亮
-
🔄 预览区域和识别结果双向联动
-
📊 支持 JSON 格式结果展示
-
🎨 TODO:可自定义样式和主题
安装与使用
拉取项目
git clone https://github.com/intsig-textin/textin-ocr-frontend.git
npm install textin-ocr-frontend
# 或
yarn add textin-ocr-frontend
快速开始
import { FilePreview, ResultView, JsonView } from "textin-ocr-frontend";functionApp() {
return (<div style={{ display: "flex" }}><div style={{ flex: 1 }}><FilePreview src="path/to/image.jpg" rects={rects} pages={pages} /></div><div style={{ flex: 1 }}><ResultView resultList={resultList} /></div></div>);
}
组件说明
1. FilePreview 文件预览组件
文件预览组件,支持 PDF 和图片预览,支持缩放、旋转、分页等功能。
Props
2. ResultView 结果展示组件
结果展示组件,支持表格和列表两种展示方式。
Props
3. MarkLayer 标注层组件
标注层组件,用于在图片显示标注框。
Props
4. JsonView JSON 展示组件
JSON 数据展示组件,用于格式化展示 JSON 数据。 本项目 JSON 数据采用react-json-view
库渲染,API 保持一致,详细属性可参考其官方文档。
Props
API Interface 定义
PDFSrc
PDF 文件源配置
interface DocumentInitParameters {[key: string]: any;url?: string | URL;data?: TypedArray | ArrayBuffer | Array<number> | string;httpHeaders?: Object;withCredentials?: boolean;password?: string;length?: boolean;
}type PDFSrc = DocumentInitParameters;
IRectItem
标注框数据
interface IRectItem {[key: string]: any;key?: string;type?: string;rect_type?: string;uid: string;parent_uid?: string;content_id: string;parent_id?: string;position: number[];angle?: number;render_text?: string;
}
IPageItem
页面数据
interface IPageItem {page_number: number;duration: number;ppi: number;width: number;height: number;angle?: number;
}
IResultListItem
结果列表项
interface IResultListItem extends IRectItem {type: string;description: string;no: number;list: IFieldItem[];flightList: IFieldItem[][];page_id?: number;
}
IFieldItem
字段项
interface IFieldItem extends IOriginFieldItem {uid: string;parent_uid?: string;
}interface IOriginFieldItem {key: string;type?: string;value: string;description: string;position: number[];
}
ToolbarOptions
工具栏配置
interface ToolbarOptions {tools: PreviewToolItem[];
}interface PreviewToolItem {Icon: React.ComponentType<any>;onClick: () => void;type: string;disabled?: boolean;
}
PreviewToolItem
工具栏配置项
interface PreviewToolItem {Icon: React.ComponentType<any>; // 工具栏图标组件onClick: () => void; // 点击事件处理函数type: string; // 工具类型disabled?: boolean; // 是否禁用
}
Hooks
useContentLinkage
用于实现预览区域和识别结果的双向联动。
const { activeContentId, activeParentContentId, registerLinkage } =useContentLinkage({viewContainerRef,resultContainerRef,});
参数
返回值
usePDFMarkLayer
用于在 PDF 文档上实现标注层功能。
const { run } = usePDFMarkLayer({containerRef,pdfViewerRef,rects,pages,dpi,activeContentId,showMark,
});
参数
返回值
usePreviewTool
用于实现预览工具栏功能,包括缩放、旋转和 1:1 还原。
const { tools, scale, rotate, position, onMouseDown, onWheel, resizeScale } =usePreviewTool({viewContainerRef,viewRef,toolbarOptions,});
参数
返回值
示例
图片示例
import { useLayoutEffect, useRef, useState } from "react";
import FilePreview from "../components/FilePreview";
import { RadioGroup } from "../components/RadioGroup";
import ResultView from "../components/ResultView";
import { imageExample } from "./data";
import JsonView from "../components/JsonView";
import { useContentLinkage } from "../hooks/useContentLinkage";export default functionImageExample() {const [resultTab, setResultTab] = useState("text");const viewContainerRef = useRef<HTMLElement | null>(null);const resultContainerRef = useRef<HTMLElement | null>(null);const { activeParentContentId, activeContentId, registerLinkage } =useContentLinkage({viewContainerRef,resultContainerRef,});useLayoutEffect(() => {registerLinkage();}, []);return (<divstyle={{display: "flex",width: "100%",height: "calc(100% - 80px)",padding: 16,textAlign: "center",columnGap: 32,}}><div style={{ flex: 4, minWidth: "40%", maxWidth: "60%" }}><div style={{ margin: 16 }}>预览</div><divstyle={{position: "relative",overflow: "hidden",maxWidth: "100%",maxHeight: "calc(100% - 80px)",height: "calc(100% - 80px)",}}><FilePreviewsrc={imageExample.src}rects={imageExample.rects}pages={imageExample.pages}getContainerRef={viewContainerRef}activeContentId={activeContentId}/></div></div><div style={{ flex: 6, minWidth: "40%", maxWidth: "60%" }}><RadioGroupstyle={{ margin: 16 }}optionStyle={{ flex: 1 }}type="line"options={[{ label: "识别结果", value: "text" },{ label: "JSON结果", value: "json" },]}value={resultTab}onChange={setResultTab}/>{resultTab === "text" && (<ResultViewstyle={{position: "relative",overflow: "auto",maxWidth: "100%",maxHeight: "calc(100% - 80px)",height: "calc(100% - 80px)",}}// resultList={example2.result}resultList={imageExample.result}getContainerRef={resultContainerRef}activeContentId={activeContentId}activeParentContentId={activeParentContentId}/>)}{resultTab === "json" && (<JsonViewstyle={{padding: "0 16px",height: "calc(100% - 80px)",overflow: "auto",}}src={imageExample.json}/>)}</div></div>);
}
PDF 示例
import { useLayoutEffect, useRef, useState } from "react";
import FilePreview from "../components/FilePreview";
import { RadioGroup } from "../components/RadioGroup";
import ResultView from "../components/ResultView";
import { pdfExample } from "./data";
import JsonView from "../components/JsonView";
import { useContentLinkage } from "../hooks/useContentLinkage";export default functionPDFExample() {const [resultTab, setResultTab] = useState("text");const viewContainerRef = useRef<HTMLElement | null>(null);const resultContainerRef = useRef<HTMLElement | null>(null);const { activeParentContentId, activeContentId, registerLinkage } =useContentLinkage({viewContainerRef,resultContainerRef,});useLayoutEffect(() => {registerLinkage();}, []);return (<divstyle={{display: "flex",width: "100%",height: "calc(100vh - 100px)",padding: 16,textAlign: "center",columnGap: 32,}}><div style={{ flex: 4, minWidth: "40%", maxWidth: "60%" }}><div style={{ margin: 16 }}>预览</div><divstyle={{position: "relative",overflow: "hidden",maxWidth: "100%",maxHeight: "calc(100% - 80px)",height: "calc(100% - 80px)",}}><FilePreviewsrc={{url: pdfExample.src,}}rects={pdfExample.rects}pages={pdfExample.pages}getContainerRef={viewContainerRef}activeContentId={activeContentId}/></div></div><div style={{ flex: 6, minWidth: "40%", maxWidth: "60%" }}><RadioGroupstyle={{ margin: 16 }}optionStyle={{ flex: 1 }}type="line"options={[{ label: "识别结果", value: "text" },{ label: "JSON结果", value: "json" },]}value={resultTab}onChange={setResultTab}/>{resultTab === "text" && (<ResultViewstyle={{position: "relative",overflow: "auto",maxWidth: "100%",maxHeight: "calc(100% - 80px)",height: "calc(100% - 80px)",}}resultList={pdfExample.result}getContainerRef={resultContainerRef}activeContentId={activeContentId}activeParentContentId={activeParentContentId}/>)}{resultTab === "json" && (<JsonViewstyle={{padding: "0 16px",height: "calc(100% - 80px)",overflow: "auto",}}src={pdfExample.json}/>)}</div></div>);
}
二次开发
项目基于 vite 和 react 构建,您可将该项目 fork 到本地自主扩展:
拉取项目
git clone https://github.com/intsig-textin/textin-ocr-frontend.git
安装依赖
npm install
启动项目
npm run dev
浏览器访问 http://localhost:5173/
在线预览前端界面:https://cc.co/16YSTY
以上为 TextIn OCR Frontend 开源组件库当前版本介绍。根据规划,组件库将持续迭代,实现:
-
组件支持更多自定义配置、样式覆盖等特性
-
支持可编辑、复制、导出结果
-
支持更多复杂类型识别结果展示
在线体验https://cc.co/16YSTY