Unverified Commit bcbbee8c authored by Xiaomeng Zhao's avatar Xiaomeng Zhao Committed by GitHub
Browse files

Merge pull request #2622 from myhloli/dev

Dev
parents 3cc3f754 ced5a7b4
import styles from './loadingAnimation.module.scss';
interface ILoadingAnimationProps {
className?: string;
}
const LoadingAnimation = (props: ILoadingAnimationProps) => {
const { className } = props;
return <div className={`${styles.loader} ${className}`}></div>;
};
export default LoadingAnimation;
.loader {
width: 14px;
height: 14px;
border-radius: 50%;
display: inline-block;
position: relative;
/* stylelint-disable-next-line alpha-value-notation */
background: linear-gradient(0deg, rgba(13,83,222,1) 0%, rgba(43,105,226,1) 30%, rgba(13, 20, 222, 0) 100%);
box-sizing: border-box;
animation: rotation 1.5s linear infinite;
}
.loader::after {
content: '';
box-sizing: border-box;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 10px;
height: 10px;
border-radius: 50%;
background: #fff;
}
@keyframes rotation {
0% { transform: rotate(0deg) }
100% { transform: rotate(360deg)}
}
.textTooltip {
:global {
.ant-tooltip-arrow {
// display: none !important;
}
.ant-tooltip-inner, .ant-tooltip-content, .ant-tooltip-inner-content {
padding: 0px !important;
border-radius: 4px !important;
overflow: hidden;
}
}
}
import { Popover, Tooltip } from 'antd';
import React, { useRef, useState } from 'react';
import styles from './index.module.scss';
import { RefObject } from 'react';
import { useIsomorphicLayoutEffect, useMemoizedFn } from 'ahooks';
export function useResizeEffect<T extends HTMLElement>(effect: (target: T) => void, targetRef: RefObject<T>) {
const fn = useMemoizedFn(effect);
useIsomorphicLayoutEffect(() => {
const target = targetRef.current;
if (!target) return;
if (window.ResizeObserver) {
let animationFrame: number;
const observer = new ResizeObserver(() => {
animationFrame = window.requestAnimationFrame(() => fn(target));
});
observer.observe(target);
return () => {
window.cancelAnimationFrame(animationFrame);
observer.disconnect();
};
} else {
fn(target);
}
}, [targetRef]);
}
interface ITextTooltip {
style?: React.CSSProperties;
str: string;
suffix?: React.ReactNode | string;
trigger?: 'hover' | 'click';
handleClick?: () => void;
}
export const TextTooltip = (props: ITextTooltip) => {
const { style = {}, str, trigger = 'click', suffix, handleClick } = props;
const rootRef = useRef<HTMLDivElement>(null);
const tooltipRef = useRef<HTMLDivElement>(null);
const [clickable, setClickable] = useState(false);
function calcEllipsised() {
// 没有被截断
if (tooltipRef!?.current!?.scrollWidth > tooltipRef!?.current!?.clientWidth) {
setClickable(true);
} else {
setClickable(false);
}
}
useResizeEffect(calcEllipsised, rootRef);
return (
<Tooltip
title={<div className="bg-black/[0.85] text-white p-[6px]">{str}</div>}
trigger={clickable ? trigger : ('' as 'click')}
overlayClassName={styles.textTooltip}
style={{ width: '100%' }}
zIndex={999999}
placement="right"
align={{
offset: [72, 0]
}}
>
<div style={{ width: '100%', ...style }} className="flex" ref={rootRef}>
<div className="text-ellipsis overflow-hidden whitespace-nowrap" ref={tooltipRef}>
<span onClick={() => handleClick?.()}>{str}</span>
</div>
{suffix}
</div>
</Tooltip>
);
};
// cl 2022/4/21 18:22
import { customUploadToOss } from "@/api/oss";
import { Upload as AntdUpload } from "antd";
import { DraggerProps, UploadProps } from "antd/es/upload";
import React from "react";
interface IProps extends UploadProps, DraggerProps {
isDragger?: boolean;
openRead?: boolean;
taskType?: string;
changeOption?: (option: any) => any;
}
const Upload: React.FC<IProps> = (props) => {
const { isDragger, openRead, taskType, changeOption, ...rest } = props;
const Component = isDragger ? AntdUpload.Dragger : AntdUpload;
return (
<Component
{...rest}
customRequest={(options: any) =>
customUploadToOss(changeOption ? changeOption?.(options) : options, {
openRead: openRead || false,
fileType: taskType || "pdf",
uploadType: "local",
})
}
>
{props.children}
</Component>
);
};
export default Upload;
export const PDF_DRIVE_MD = "pdf-drive-md";
export const MD_DRIVE_PDF = "pdf-drive-md";
export const ADD_TASK_LIST = "add-task-list";
export const UPDATE_TASK_LIST = "update-task-list";
export enum Language {
ZH_CN = "zh-CN",
EN_US = "en-US",
}
export const PDF_COLOR_PICKER = {
title: {
line: 'rgba(121, 124, 255, 1)',
fill: 'rgba(121, 124, 255, 0.4)'
},
text: {
line: 'rgba(230, 122, 171, 1)',
fill: 'rgba(230, 122, 171, 0.4)'
},
interline_equation: {
line: 'rgba(240, 240, 124, 1)',
fill: 'rgba(240, 240, 124, 0.4)'
},
discarded: {
line: 'rgba(164,164,164,1)',
fill: 'rgba(164,164,164,0.4)'
},
image: {
line: 'rgba(149, 226, 115, 1)',
fill: 'rgba(149, 226, 115, 0.4)'
},
table: {
line: 'rgba(230, 113, 230, 1)',
fill: 'rgba(230, 113, 230, 0.4)'
},
inline_equation: {
line: 'rgba(150, 232, 172, 1)',
fill: 'rgba(150, 232, 172, 0.4)'
}
};
export const DEFAULT_COLOR_SECTION = {
line: 'rgba(166, 113, 230, 1)',
fill: 'rgba(166, 113, 230, 0.4)'
};
export const PDF_TEMPLATE_URL_KEY = 't';
\ No newline at end of file
export enum Path {
Home = "/",
Settings = "/settings",
}
export enum SlotID {
AppBody = "app-body",
}
export const LOCALE_STORAGE_KEY = "locale-minerU"
\ No newline at end of file
import React from "react";
import { IntlProvider } from "react-intl";
import { useLanguageStore } from "@/store/languageStore";
import contentEn from "@/locale/en.json";
import contentZh from "@/locale/zh.json";
import sideEn from "@/locale/side/en.ts";
import sideZh from "@/locale/side/zh.ts";
import commonEn from "@/locale/common/en.json";
import commonZh from "@/locale/common/zh.json";
import { Language } from "@/constant";
const messages = {
[Language.EN_US]: {
...contentEn,
...sideEn,
...commonEn,
},
[Language.ZH_CN]: {
...contentZh,
...sideZh,
...commonZh,
},
};
export const LanguageProvider: React.FC<{ children: React.ReactNode }> = ({
children,
}) => {
const { language } = useLanguageStore();
return (
<IntlProvider
messages={messages[language] as unknown as Record<string, string>}
locale={language}
defaultLocale="en"
>
{children}
</IntlProvider>
);
};
// QueryProvider.tsx
import React from "react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
const defaultQueryClientConfig = {
defaultOptions: {
queries: {
retry: false,
refetchOnWindowFocus: false,
staleTime: 5 * 60 * 1000, // 5 minutes
},
},
};
interface QueryProviderProps {
children: React.ReactNode;
}
const QueryProvider: React.FC<QueryProviderProps> = ({ children }) => {
const queryClient = new QueryClient({
...defaultQueryClientConfig,
});
return (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
);
};
export default QueryProvider;
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(0, 0, 0, 0.87);
background-color: white;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
{
"common.cancel": "Cancel",
"common.confirm": "Confirm",
"common.retry": "retry"
}
\ No newline at end of file
{
"common.cancel": "取消",
"common.confirm": "确定",
"common.retry": "retry"
}
\ No newline at end of file
{
"extractor.common.upload": "Click to upload file",
"extractor.common.try": "Try:",
"extractor.home": "Home",
"extractor.button.download": "Download",
"extractor.button.lineWrap": "Line Wrap",
"extractor.button.fullScreen": "Fullscreen",
"extractor.button.exitFullScreen": "Exit Fullscreen",
"extractor.button.showLayer": "Display recognition results",
"extractor.button.hiddenLayer": "Hide recognition results",
"extractor.error": "Extraction failed",
"extractor.law": "Please ensure that the documents you upload are legal and compliant, and we do not assume legal responsibility for the content of the documents. Data Protection Policy Children's Information Protection Policy Service Agreement | © All Rights Reserved.Shanghai ICP 2021009351-21",
"extractor.button.reUpload": "Re-Upload",
"extractor.failed": "Unable to extract, no data to display yet",
"extractor.common.extracting": "Extracting, please wait",
"extractor.common.extracting.queue": "Queuing for extraction, currently ranked at {id}",
"extractor.common.loading": "Loading",
"extractor.common.pdf.demo1": "Example1.pdf",
"extractor.common.pdf.demo2": "Example2.pdf",
"extractor.common.formula.detect.demo1": "FormulaDetail1.jpg",
"extractor.common.formula.extract.demo1": "FormulaExtract1.jpg",
"extractor.common.login.desc": "Functionality available after login",
"extractor.markdown.preview": "Preview",
"extractor.markdown.code": "Code",
"extractor.home.title": "Welcome to Miner U",
"extractor.home.subTitle": "Upload documents and intelligently extract them into Markdown format",
"extractor.side.extractTask": "Extraction Tasks",
"extractor.side.extractTask.title": "Please upload a PDF document within 5M (within 10 pages) or a JPG/PNG image",
"extractor.pdf.title": "PDF Document Extraction",
"extractor.pdf.subTitle": "Supports text/scanned PDF parsing, identifies various layout elements and converts them into multimodal Markdown format",
"extractor.common.pdf.upload.tip": "Please upload a PDF document",
"extractor.pdf.ocr": "OCR Identify Pattern",
"extractor.pdf.ocr.popover": "By default, PDF types (text-based, scanned) will be automatically recognized, and based on the recognition results, you can choose to use text recognition or OCR recognition. If enabled, all types of PDF will be recognized by OCR.",
"extractor.formula.title2": "Recognize mathematical formulas in images as LaTex format, support multi-line formulas and handwritten formula recognition",
"extractor.formula.title": "Locate the formulas within and between rows in the image and generate bounding boxes",
"extractor.formula.upload.text": "Click to upload an image",
"extractor.formula.popover.extract": "In order to obtain the best formula recognition effect, please crop the image, focus on the formula part, and upload a clear, watermark-free image of the mathematical formula, as shown below",
"extractor.formula.popover.detect": "In order to get the best formula recognition effect, please upload clear, non-watermarked images containing mathematical formulas, as shown below",
"extractor.formula.upload.accept": "Please upload a JPG/PNG image within 5M",
"extractor.formula.upload.try": "Please upload an image containing a mathematical formula Example: ",
"extractor.guide.title": "Welcome to use more open source products 🎉",
"extractor.queue": "Extract records",
"extractor.queue.delete": "Confirm to delete this file?",
"extractor.queue.extracting": "Extracting",
"extractor.feedback.title1": "Are you satisfied with the overall extraction performance?",
"extractor.feedback.title3": "Look forward to your suggestions to help us better optimize",
"extractor.feedback.up.title": "What improvements are you expecting to see?",
"extractor.feedback.down.title": "What is the reason for your dissatisfaction? ",
"extractor.feedback.up": "Satisfied",
"extractor.feedback.down": "Dissatisfied",
"extractor.feedback.input.placeholder": "Please enter your suggestions for improvement",
"extractor.feedback.input.submit": "Submit",
"extractor.feedback.success": "Thank you for the feedback",
"extractor.queue.delete.success": "Delete successfully"
}
\ No newline at end of file
import { EXTRACTOR_TYPE_LIST } from "@/types/extract-task-type";
import odlLogo from "@/assets/pdf/odl-logo.svg";
import labelLLMLogo from "@/assets/pdf/label-llm.svg";
import labelULogo from "@/assets/pdf/labelU.svg";
export default {
"extractor.side.tabList": [
{
label: "PDF Extraction",
type: EXTRACTOR_TYPE_LIST.pdf,
},
// {
// label: "Formula Extraction",
// type: EXTRACTOR_TYPE_LIST.formula,
// },
],
"extractor.side.guide_list": [
{
type: "odl",
icon: odlLogo,
title: "OpenDataLab",
desc: "Covers a huge amount of high-quality, multimodal datasets",
goToText: "Go Now",
link: "https://opendatalab.com",
},
{
type: "labelU",
icon: labelULogo,
title: "Label U Labeling Tool",
desc: "Lightweight open source annotation tools",
goToText: "github",
link: "https://github.com/opendatalab/labelU",
},
{
type: "labelLLM",
icon: labelLLMLogo,
[`zh-CN-title`]: "LabelLLM Labeling Tool",
title: "LabelLLM Labeling Tool",
desc: "Specializing in dialogue annotation for large language models",
goToText: "github",
link: "https://github.com/opendatalab/LabelLLM",
},
],
};
import { EXTRACTOR_TYPE_LIST } from "@/types/extract-task-type";
import odlLogo from "@/assets/pdf/odl-logo.svg";
import labelLLMLogo from "@/assets/pdf/label-llm.svg";
import labelULogo from "@/assets/pdf/labelU.svg";
export default {
"extractor.side.tabList": [
{
label: "PDF文档提取",
type: EXTRACTOR_TYPE_LIST.pdf,
},
// {
// label: "公式检测与识别",
// type: EXTRACTOR_TYPE_LIST.formula,
// },
],
"extractor.side.guide_list": [
{
type: "odl",
icon: odlLogo,
title: "OpenDataLab",
desc: "涵盖海量优质、多模态数据集",
goToText: "立即前往",
link: "https://opendatalab.com",
},
{
type: "labelU",
icon: labelULogo,
title: "Label U 标注工具",
desc: "轻量级开源标注工具",
goToText: "github",
link: "https://github.com/opendatalab/labelU",
},
{
type: "labelLLM",
icon: labelLLMLogo,
title: "LabelLLM 标注工具",
desc: "专攻于大模型的对话标注",
goToText: "github",
link: "https://github.com/opendatalab/LabelLLM",
},
],
};
{
"extractor.common.upload": "点击上传文件",
"extractor.common.try": "试一试:",
"extractor.home": "首页",
"extractor.button.download": "下载",
"extractor.button.lineWrap": "换行",
"extractor.button.fullScreen": "全屏",
"extractor.button.exitFullScreen": "退出全屏",
"extractor.button.showLayer": "显示识别结果",
"extractor.button.hiddenLayer": "隐藏识别结果",
"extractor.button.reUpload": "重新上传",
"extractor.error": "提取失败",
"extractor.common.loading": "加载中",
"extractor.law": "请确保您上传的文件合法合规,我们不承担因文件内容产生的法律责任。《信息保护政策》 《儿童信息保护政策》《服务协议》|© All Rights Reserved.沪ICP备2021009351号-21",
"extractor.failed": "不可提取,暂无可展示数据",
"extractor.common.extracting": "提取中,请稍等",
"extractor.common.extracting.queue": "正在排队提取,当前排在第 {id} 位",
"extractor.common.pdf.demo1": "示例1.pdf",
"extractor.common.pdf.demo2": "示例2.pdf",
"extractor.common.formula.detect.demo1": "公式检测1.jpg",
"extractor.common.formula.extract.demo1": "公式识别1.jpg",
"extractor.common.login.desc": "登录后可使用完整功能",
"extractor.markdown.preview": "预览",
"extractor.markdown.code": "代码",
"extractor.home.title": "欢迎使用 Miner U",
"extractor.home.subTitle": "上传文档,智能提取为 Markdown 格式",
"extractor.side.extractTask": "提取任务",
"extractor.side.extractTask.title": "请上传 5M 以内的 PDF 文档 ( 10 页以内)或 JPG/PNG 图片",
"extractor.pdf.title": "PDF文档提取",
"extractor.pdf.subTitle": "支持文本/扫描型 PDF 解析,识别各类版面元素并转换为多模态 Markdown 格式",
"extractor.common.pdf.upload.tip": "请上传 PDF 文档",
"extractor.pdf.ocr": "OCR 识别模式",
"extractor.pdf.ocr.popover": " 默认将自动识别PDF类型(文本型、扫描型),并根据识别结果选择采用文本识别或者OCR识别方式。 如开启,将对所有类型PDF采用OCR识别方式。",
"extractor.formula.title": "定位图片中的行内、行间公式,生成边界框",
"extractor.formula.title2": "将图片中的数学公式识别为 laTex 格式,支持多行公式、手写公式识别",
"extractor.formula.upload.text": "点击上传图片",
"extractor.formula.popover.extract": "为获得最佳的公式识别效果,请上传清晰、无水印的包含数学公式的图片,如下图",
"extractor.formula.popover.detect": "为获得最佳的公式识别效果,请裁剪图片,聚焦公式部分,上传清晰、无水印的数学公式图片,如下图",
"extractor.formula.upload.accept": "请上传 5M 以内的JPG/PNG 图片",
"extractor.formula.upload.try": "请上传包含数学公式的图片 示例:",
"extractor.guide.title": "欢迎使用更多开源产品 🎉",
"extractor.queue": "提取记录",
"extractor.queue.delete": "确认删除此文件?",
"extractor.queue.extracting": "提取中",
"extractor.feedback.title1": "您对整体提取效果是否满意 ?",
"extractor.feedback.title3": "期待您的建议,帮助我们更好的优化",
"extractor.feedback.up.title": "您期望看到哪些改进?",
"extractor.feedback.down.title": "您感到不满意的原因是?",
"extractor.feedback.up": "满意",
"extractor.feedback.down": "不满意",
"extractor.feedback.input.placeholder": "请输入您的改进建议",
"extractor.feedback.input.submit": "提交",
"extractor.feedback.success": "感谢你的反馈",
"extractor.queue.delete.success": "删除成功"
}
\ No newline at end of file
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.tsx'
import './index.css'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment