diff --git a/package.json b/package.json
index 73826ce..6fbcc3d 100644
--- a/package.json
+++ b/package.json
@@ -38,7 +38,9 @@
"react-is": "18.3.1",
"react-router-dom": "^7.9.4",
"uuid": "^13.0.0",
- "zustand": "^5.0.8"
+ "zustand": "^5.0.8",
+ "@monaco-editor/react": "^4.6.0",
+ "monaco-editor": "^0.52.2"
},
"devDependencies": {
"@eslint/js": "^9.36.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 3815f8d..aac5b90 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -14,6 +14,9 @@ importers:
'@emotion/styled':
specifier: ^11.14.1
version: 11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react@18.3.1)
+ '@monaco-editor/react':
+ specifier: ^4.6.0
+ version: 4.7.0(monaco-editor@0.52.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@mui/icons-material':
specifier: ^7.3.4
version: 7.3.4(@mui/material@7.3.4(@emotion/react@11.14.0(@types/react@19.2.2)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@19.2.2)(react@18.3.1)
@@ -59,6 +62,9 @@ importers:
loglevel:
specifier: ^1.9.2
version: 1.9.2
+ monaco-editor:
+ specifier: ^0.52.2
+ version: 0.52.2
pdfjs-dist:
specifier: ^5.4.394
version: 5.4.394
@@ -8785,6 +8791,9 @@ packages:
moment@2.30.1:
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
+ monaco-editor@0.52.2:
+ resolution: {integrity: sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==}
+
monaco-editor@0.54.0:
resolution: {integrity: sha512-hx45SEUoLatgWxHKCmlLJH81xBo0uXP4sRkESUpmDQevfi+e7K1VuiSprK6UpQ8u4zOcKNiH0pMvHvlMWA/4cw==}
@@ -14016,6 +14025,13 @@ snapshots:
dependencies:
state-local: 1.0.7
+ '@monaco-editor/react@4.7.0(monaco-editor@0.52.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@monaco-editor/loader': 1.6.1
+ monaco-editor: 0.52.2
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
'@monaco-editor/react@4.7.0(monaco-editor@0.54.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@monaco-editor/loader': 1.6.1
@@ -22253,6 +22269,8 @@ snapshots:
moment@2.30.1: {}
+ monaco-editor@0.52.2: {}
+
monaco-editor@0.54.0:
dependencies:
dompurify: 3.1.7
diff --git a/src/interfaces/database/knowledge.ts b/src/interfaces/database/knowledge.ts
index 1e3e98d..fde150c 100644
--- a/src/interfaces/database/knowledge.ts
+++ b/src/interfaces/database/knowledge.ts
@@ -279,6 +279,10 @@ export interface IKnowledgeFile {
name: string;
/** 解析器ID */
parser_id: string;
+ /** 流水线ID,可选 */
+ pipeline_id?: string;
+ /** 流水线名称,可选 */
+ pipeline_name?: string;
/** 处理开始时间,可选 */
process_begin_at?: any;
/** 处理持续时间 */
diff --git a/src/locales/en.ts b/src/locales/en.ts
index 944ecf6..6563f05 100644
--- a/src/locales/en.ts
+++ b/src/locales/en.ts
@@ -601,6 +601,7 @@ export default {
redo: 'Do you want to clear the existing {{chunkNum}} chunks?',
setMetaData: 'Set Meta Data',
pleaseInputJson: 'Please enter JSON',
+ invalidJson: 'Invalid JSON format',
documentMetaTips: `
The meta data is in Json format(it's not searchable). It will be added into prompt for LLM if any chunks of this document are included in the prompt.
Examples:
The meta data is:
diff --git a/src/locales/zh.ts b/src/locales/zh.ts
index 0eac524..8e6c6f6 100644
--- a/src/locales/zh.ts
+++ b/src/locales/zh.ts
@@ -595,6 +595,7 @@ export default {
redo: '是否清空已有 {{chunkNum}}个 chunk?',
setMetaData: '设置元数据',
pleaseInputJson: '请输入JSON',
+ invalidJson: '无效的JSON格式',
documentMetaTips: `元数据为 Json 格式(不可搜索)。如果提示中包含此文档的任何块,它将被添加到 LLM 的提示中。
示例:
元数据为:
diff --git a/src/pages/knowledge/components/DocumentListComponent.tsx b/src/pages/knowledge/components/DocumentListComponent.tsx
index 4528ac1..01a8629 100644
--- a/src/pages/knowledge/components/DocumentListComponent.tsx
+++ b/src/pages/knowledge/components/DocumentListComponent.tsx
@@ -58,6 +58,9 @@ import dayjs from 'dayjs';
import logger from '@/utils/logger';
import { LanguageAbbreviation } from '@/constants/common';
import knowledgeService from '@/services/knowledge_service';
+import ParserContextMenu from './ParserContextMenu';
+import DocumentParserDialog from './DocumentParserDialog';
+import DocumentMetadataDialog from './DocumentMetadataDialog';
interface DocumentListComponentProps {
@@ -215,6 +218,15 @@ const DocumentListComponent: React.FC = ({
const [renameDialogOpen, setRenameDialogOpen] = useState(false);
const [newFileName, setNewFileName] = useState('');
+ // parser 列右键菜单与对话框状态
+ const [parserMenuAnchor, setParserMenuAnchor] = useState(null);
+ const [parserMenuFile, setParserMenuFile] = useState(undefined);
+ const [parserDialogOpen, setParserDialogOpen] = useState(false);
+ const [metadataDialogOpen, setMetadataDialogOpen] = useState(false);
+ // 打开对话框时使用的文件,避免关闭菜单时清空导致对话框拿不到文件
+ const [dialogFile, setDialogFile] = useState(undefined);
+ // 解析与元数据对话框提交状态由子组件内部管理
+
const { i18n, t } = useTranslation();
// 根据当前语言获取DataGrid的localeText
@@ -346,6 +358,19 @@ const DocumentListComponent: React.FC = ({
setSelectedSuffix(typeof value === 'string' ? value.split(',') : value);
};
+ // 打开 parser 列的上下文菜单
+ const handleOpenParserMenu = (event: React.MouseEvent, file: IKnowledgeFile) => {
+ event.stopPropagation();
+ event.preventDefault();
+ setParserMenuAnchor(event.currentTarget);
+ setParserMenuFile(file);
+ };
+
+ const handleCloseParserMenu = () => {
+ setParserMenuAnchor(null);
+ setParserMenuFile(undefined);
+ };
+
// 选中数量计算(强类型)
const countSelected = (model: GridRowSelectionModel, totalCount: number): number => {
const size = model.ids.size ?? 0;
@@ -380,7 +405,7 @@ const DocumentListComponent: React.FC = ({
field: 'name',
headerName: t('knowledge.fileName'),
flex: 2,
- minWidth: 200,
+ minWidth: 120,
cellClassName: 'grid-center-cell',
renderCell: (params) => (
= ({
),
},
+ {
+ field: 'create_time',
+ headerName: t('knowledge.uploadTime'),
+ flex: 1,
+ minWidth: 140,
+ valueFormatter: (value) => dayjs(value).format('YYYY-MM-DD HH:mm:ss'),
+ },
{
field: 'type',
headerName: t('knowledge.type'),
@@ -446,11 +478,15 @@ const DocumentListComponent: React.FC = ({
renderCell: (params) => getRunStatusChip(params.value, params.row.progress),
},
{
- field: 'create_time',
- headerName: t('knowledge.uploadTime'),
- flex: 1,
- minWidth: 140,
- valueFormatter: (value) => dayjs(value).format('YYYY-MM-DD HH:mm:ss'),
+ field: 'parser_id',
+ headerName: t('knowledge.parser'),
+ flex: 0.8,
+ minWidth: 100,
+ renderCell: (params) => (
+ handleOpenParserMenu(e, params.row)} onClick={(e) => handleOpenParserMenu(e, params.row)}>
+
+
+ ),
},
{
field: 'actions',
@@ -680,6 +716,23 @@ const DocumentListComponent: React.FC = ({
/>
+ {/* Parser 列上下文菜单 */}
+ {
+ setDialogFile(parserMenuFile);
+ setParserDialogOpen(true);
+ handleCloseParserMenu();
+ }}
+ onOpenMetadata={() => {
+ setDialogFile(parserMenuFile);
+ setMetadataDialogOpen(true);
+ handleCloseParserMenu();
+ }}
+ />
+
{/* 菜单 */}