diff --git a/web/src/api/knowledgeBase.ts b/web/src/api/knowledgeBase.ts
index 38a0d40d..1353067e 100644
--- a/web/src/api/knowledgeBase.ts
+++ b/web/src/api/knowledgeBase.ts
@@ -220,6 +220,21 @@ export const createDocumentAndUpload = async ( data: any, params: PathQuery) =>
const response = await request.post(`${apiPrefix}/files/customtext`, data, { params } );
return response as any;
};
+// web feishu yuque
+export const createSync = async (knowledge_id: string) => {
+ const response = await request.post(`${apiPrefix}/knowledges/${knowledge_id}/sync`);
+ return response as any;
+};
+// check feishu
+export const checkFeishuSync = async (params: any) => {
+ const response = await request.get(`${apiPrefix}/knowledges/check/feishu/auth`, undefined, { params });
+ return response as any;
+};
+// check yuque
+export const checkYuqueSync = async (params: any) => {
+ const response = await request.get(`${apiPrefix}/knowledges/check/yuque/auth`, undefined, { params });
+ return response as any;
+};
// 更新文档
export const updateDocument = async (id: string, data: KnowledgeBaseDocumentData) => {
const response = await request.put(`${apiPrefix}/documents/${id}`, data);
diff --git a/web/src/i18n/en.ts b/web/src/i18n/en.ts
index d3c788df..381c6578 100644
--- a/web/src/i18n/en.ts
+++ b/web/src/i18n/en.ts
@@ -597,6 +597,18 @@ export const en = {
last_at: 'Last Updated',
private: 'Private',
share: 'Share',
+ syncNow: 'Sync Now',
+ syncing: 'Syncing...',
+ syncSuccess: 'Sync started successfully',
+ syncCompleted: 'Sync completed, data loaded successfully',
+ syncTimeout: 'Sync timeout (1 minute), please try again later or check the sync status',
+ syncFailed: 'Sync failed',
+ syncError: 'Unable to sync, knowledge base not found',
+ yuqueAuthRequired: 'Please enter Yuque User ID and Token',
+ yuqueAuthSuccess: 'Yuque authentication successful',
+ feishuAuthRequired: 'Please enter Feishu App ID, App Secret and Folder Token',
+ feishuAuthSuccess: 'Feishu authentication successful',
+ authFailed: 'Authentication failed, please check your credentials',
recallTest: 'Recall Test',
testQuestion: 'Test Question',
doc_num: 'Document Number',
@@ -636,6 +648,7 @@ export const en = {
customText: 'Custom Text',
customContent: 'Custom Content',
createContentError: 'Failed to create custom content',
+ createLinkError: 'Failed to create link content',
manuallyInputText: 'Manually input a text as dataset',
importTemplate: 'Template Import',
importBackup: 'Backup Import',
@@ -835,6 +848,36 @@ export const en = {
embeddingRequired: 'Please select an embedding model',
nameRequired: 'Please enter a name',
modelRequired: 'Please select a model',
+ entryUrl: 'Entry URL',
+ entryUrlRequired: 'Please enter entry URL',
+ entryUrlInvalid: 'Please enter a valid URL',
+ maxPages: 'Max Pages',
+ maxPagesRequired: 'Please enter max pages',
+ delaySeconds: 'Delay Seconds',
+ delaySecondsRequired: 'Please enter delay seconds',
+ timeoutSeconds: 'Timeout Seconds',
+ timeoutSecondsRequired: 'Please enter timeout seconds',
+ userAgent: 'User Agent',
+ userAgentRequired: 'Please enter user agent',
+ platform: 'Platform',
+ platformRequired: 'Please select a platform',
+ yuque: 'Yuque',
+ feishu: 'Feishu',
+ yuqueUserId: 'User ID',
+ yuqueUserIdRequired: 'Please enter Yuque User ID',
+ yuqueUserIdPlaceholder: 'Enter your Yuque User ID',
+ yuqueToken: 'Token',
+ yuqueTokenRequired: 'Please enter Yuque Token',
+ yuqueTokenPlaceholder: 'Enter your Yuque Token',
+ feishuAppId: 'Feishu Application ID',
+ feishuAppIdRequired: 'Please enter Feishu Application ID',
+ feishuAppIdPlaceholder: 'Enter your Feishu Application ID',
+ feishuAppSecret: 'Feishu Application Secret',
+ feishuAppSecretRequired: 'Please enter Feishu Application Secret',
+ feishuAppSecretPlaceholder: 'Enter your Feishu Application Secret',
+ feishuFolderToken: 'Folder Token',
+ feishuFolderTokenRequired: 'Please enter Folder Token',
+ feishuFolderTokenPlaceholder: 'Enter your Feishu Folder Token',
}
},
api: {
diff --git a/web/src/i18n/zh.ts b/web/src/i18n/zh.ts
index 4e1e52e4..7b85a90d 100644
--- a/web/src/i18n/zh.ts
+++ b/web/src/i18n/zh.ts
@@ -139,6 +139,18 @@ export const zh = {
last_at: '最后更新',
private: '私有',
share: '分享',
+ syncNow: '立即同步',
+ syncing: '同步中...',
+ syncSuccess: '同步已启动',
+ syncCompleted: '同步完成,数据加载成功',
+ syncTimeout: '同步超时(1分钟),请稍后重试或检查同步状态',
+ syncFailed: '同步失败',
+ syncError: '无法同步,未找到知识库',
+ yuqueAuthRequired: '请输入语雀用户 ID 和 Token',
+ yuqueAuthSuccess: '语雀认证成功',
+ feishuAuthRequired: '请输入飞书应用 ID、应用密钥和文件夹 Token',
+ feishuAuthSuccess: '飞书认证成功',
+ authFailed: '认证失败,请检查您的凭证',
recallTest: '召回测试',
testQuestion: '测试问题',
doc_num: '文档数量',
@@ -375,6 +387,36 @@ export const zh = {
embeddingRequired: '请选择嵌入模型',
nameRequired: '请输入名称',
modelRequired: '请选择模型',
+ entryUrl: '入口网址',
+ entryUrlRequired: '请输入入口网址',
+ entryUrlInvalid: '请输入有效的网址',
+ maxPages: '最大页面数',
+ maxPagesRequired: '请输入最大页面数',
+ delaySeconds: '延迟秒数',
+ delaySecondsRequired: '请输入延迟秒数',
+ timeoutSeconds: '超时秒数',
+ timeoutSecondsRequired: '请输入超时秒数',
+ userAgent: '用户代理',
+ userAgentRequired: '请输入用户代理',
+ platform: '平台',
+ platformRequired: '请选择平台',
+ yuque: '语雀',
+ feishu: '飞书',
+ yuqueUserId: '用户 ID',
+ yuqueUserIdRequired: '请输入语雀用户 ID',
+ yuqueUserIdPlaceholder: '请输入您的语雀用户 ID',
+ yuqueToken: 'Token',
+ yuqueTokenRequired: '请输入语雀 Token',
+ yuqueTokenPlaceholder: '请输入您的语雀 Token',
+ feishuAppId: '飞书应用 ID',
+ feishuAppIdRequired: '请输入飞书应用 ID',
+ feishuAppIdPlaceholder: '请输入您的飞书应用 ID',
+ feishuAppSecret: '飞书应用密钥',
+ feishuAppSecretRequired: '请输入飞书应用密钥',
+ feishuAppSecretPlaceholder: '请输入您的飞书应用密钥',
+ feishuFolderToken: '文件夹 Token',
+ feishuFolderTokenRequired: '请输入文件夹 Token',
+ feishuFolderTokenPlaceholder: '请输入您的飞书文件夹 Token',
}
},
application: {
diff --git a/web/src/views/KnowledgeBase/[knowledgeBaseId]/CreateDataset.tsx b/web/src/views/KnowledgeBase/[knowledgeBaseId]/CreateDataset.tsx
index d2b1536f..760c4292 100644
--- a/web/src/views/KnowledgeBase/[knowledgeBaseId]/CreateDataset.tsx
+++ b/web/src/views/KnowledgeBase/[knowledgeBaseId]/CreateDataset.tsx
@@ -613,8 +613,8 @@ const CreateDataset = () => {
{t('knowledgeBase.webLink')}
-
- {t('knowledgeBase.webLinkDesc')}
+
+ {t('knowledgeBase.webLinkDesc',{count: 5})}
{t('knowledgeBase.selectorTutorial')}
diff --git a/web/src/views/KnowledgeBase/[knowledgeBaseId]/Private.tsx b/web/src/views/KnowledgeBase/[knowledgeBaseId]/Private.tsx
index 33590898..1baeb80b 100644
--- a/web/src/views/KnowledgeBase/[knowledgeBaseId]/Private.tsx
+++ b/web/src/views/KnowledgeBase/[knowledgeBaseId]/Private.tsx
@@ -14,7 +14,7 @@ import textIcon from '@/assets/images/knowledgeBase/text.png';
import editIcon from '@/assets/images/knowledgeBase/edit.png';
// import blankIcon from '@/assets/images/knowledgeBase/blankDocument.png';
// import imageIcon from '@/assets/images/knowledgeBase/image.png'
-import { getKnowledgeBaseDetail, deleteDocument, downloadFile, updateKnowledgeBase } from '@/api/knowledgeBase';
+import { getKnowledgeBaseDetail, deleteDocument, downloadFile, updateKnowledgeBase, createSync } from '@/api/knowledgeBase';
import {
type CreateModalRef,
type KnowledgeBaseListItem,
@@ -71,6 +71,9 @@ const Private: FC = () => {
const [folderTreeRefreshKey, setFolderTreeRefreshKey] = useState(0);
const [autoExpandPath, setAutoExpandPath] = useState
>([]);
const [isGraph, setIsGraph] = useState(false);
+ const [isSyncing, setIsSyncing] = useState(false);
+ const syncIntervalRef = useRef | null>(null);
+ const syncStartTimeRef = useRef(null);
const { updateBreadcrumbs } = useBreadcrumbManager({
breadcrumbType: 'detail',
// Don't provide onKnowledgeBaseMenuClick, let it use default navigation behavior (return to list page)
@@ -111,6 +114,7 @@ const Private: FC = () => {
// Convert KnowledgeBase to KnowledgeBaseListItem
const listItem = res as unknown as KnowledgeBaseListItem;
setKnowledgeBase(listItem);
+ return listItem;
} finally {
setLoading(false);
}
@@ -257,6 +261,15 @@ const Private: FC = () => {
}
}, [location.state, knowledgeBaseId, navigate, location.pathname]);
+ // Cleanup sync interval on unmount
+ useEffect(() => {
+ return () => {
+ if (syncIntervalRef.current) {
+ clearInterval(syncIntervalRef.current);
+ }
+ };
+ }, []);
+
// Handle tree node selection
const onSelect = (keys: React.Key[]) => {
if (!keys.length) {
@@ -686,11 +699,69 @@ const Private: FC = () => {
createFolderModalRef?.current?.handleOpen(f,'edit');
}
- const handleRefreshTable = () => {
- // Refresh table data
- fetchKnowledgeBaseDetail(knowledgeBase.id)
+ const handleRefreshTable = async () => {
+ // Check if sync has timed out (1 minute = 60000ms)
+ if (syncStartTimeRef.current) {
+ const elapsedTime = Date.now() - syncStartTimeRef.current;
+ if (elapsedTime > 60000) {
+ stopSyncing();
+ messageApi.warning(t('knowledgeBase.syncTimeout'));
+ return;
+ }
+ }
+
+ // Refresh table data and get updated knowledge base info
+ const updatedKnowledgeBase = await fetchKnowledgeBaseDetail(knowledgeBase.id);
tableRef.current?.loadData();
+
+ // Check if there are documents and stop syncing if so
+ if (syncStartTimeRef.current && updatedKnowledgeBase?.doc_num && updatedKnowledgeBase.doc_num > 0) {
+ stopSyncing();
+ messageApi.success(t('knowledgeBase.syncCompleted'));
+ }
}
+
+ // Handle sync for Web and Third-party knowledge bases
+ const handleSync = async () => {
+ if (!knowledgeBase?.id) {
+ messageApi.error(t('knowledgeBase.syncError'));
+ return;
+ }
+
+ try {
+ setIsSyncing(true);
+ syncStartTimeRef.current = Date.now(); // Record start time
+ await createSync(knowledgeBase.id);
+ messageApi.success(t('knowledgeBase.syncSuccess'));
+
+ // Start polling: refresh table every 5 seconds and check for data
+ syncIntervalRef.current = setInterval(async () => {
+ await handleRefreshTable();
+ }, 5000);
+
+ // Initial refresh after 1 second
+ setTimeout(async () => {
+ await handleRefreshTable();
+ }, 1000);
+
+ } catch (error) {
+ console.error('Sync failed:', error);
+ messageApi.error(t('knowledgeBase.syncFailed'));
+ setIsSyncing(false);
+ syncStartTimeRef.current = null;
+ }
+ };
+
+ // Stop syncing and clear interval
+ const stopSyncing = () => {
+ if (syncIntervalRef.current) {
+ clearInterval(syncIntervalRef.current);
+ syncIntervalRef.current = null;
+ }
+ syncStartTimeRef.current = null;
+ setIsSyncing(false);
+ };
+
return (
<>
{contextHolder}
@@ -749,9 +820,20 @@ const Private: FC = () => {
-
+ {(knowledgeBase?.type === 'Web' || knowledgeBase?.type === 'Third-party') && (
+
+ )}
+ {knowledgeBase?.type !== 'Web' && knowledgeBase?.type !== 'Third-party' && (
+
-
+
+ )}
diff --git a/web/src/views/KnowledgeBase/components/CreateModal.tsx b/web/src/views/KnowledgeBase/components/CreateModal.tsx
index 6d709a1b..b51b554f 100644
--- a/web/src/views/KnowledgeBase/components/CreateModal.tsx
+++ b/web/src/views/KnowledgeBase/components/CreateModal.tsx
@@ -1,5 +1,5 @@
import { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from 'react';
-import { Form, Input, Select, Modal, Tabs, Switch, Radio, Button,message } from 'antd';
+import { Form, Input, Select, Modal, Tabs, Switch, Radio, Button, message } from 'antd';
import { useTranslation } from 'react-i18next';
import type { KnowledgeBaseListItem, KnowledgeBaseFormData, CreateModalRef, CreateModalRefProps } from '@/views/KnowledgeBase/types';
import {
@@ -9,9 +9,12 @@ import {
updateKnowledgeBase,
getKnowledgeGraphEntityTypes,
deleteKnowledgeGraph,
- rebuildKnowledgeGraph
+ rebuildKnowledgeGraph,
+ checkFeishuSync,
+ checkYuqueSync
} from '@/api/knowledgeBase'
import RbModal from '@/components/RbModal'
+import SliderInput from '@/components/SliderInput'
const { TextArea } = Input;
const { confirm } = Modal
@@ -28,6 +31,7 @@ const CreateModal = forwardRef(({
const [modelOptionsByType, setModelOptionsByType] = useState>({});
const [datasets, setDatasets] = useState(null);
const [currentType, setCurrentType] = useState<'General' | 'Web' | 'Third-party' | 'Folder'>('General');
+ const [thirdPartyPlatform, setThirdPartyPlatform] = useState<'yuque' | 'feishu'>('yuque');
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const [activeTab, setActiveTab] = useState('basic');
@@ -51,6 +55,7 @@ const CreateModal = forwardRef(({
setActiveTab('basic');
setIsRebuildMode(false); // Reset rebuild mode flag
setOriginalType(''); // Reset original type
+ setThirdPartyPlatform('yuque'); // Reset third party platform
setVisible(false);
};
@@ -175,13 +180,13 @@ const CreateModal = forwardRef(({
: next[tp] || [];
// If there are options and current field has no value, set first option as default
- if (options.length > 0 && !form.getFieldValue(fieldKey)) {
+ if (options.length > 0 && !form.getFieldValue(fieldKey as any)) {
defaultValues[fieldKey] = options[0].value;
}
});
if (Object.keys(defaultValues).length > 0) {
- form.setFieldsValue(defaultValues as Partial);
+ form.setFieldsValue(defaultValues as any);
}
}
};
@@ -205,6 +210,7 @@ const CreateModal = forwardRef(({
};
// Process parser_config data, set default values if not present
+ const recordAny = record as any;
baseValues.parser_config = record.parser_config || {
graphrag: {
use_graphrag: false,
@@ -216,6 +222,43 @@ const CreateModal = forwardRef(({
}
};
+ // Add Third-party specific fields to parser_config if exists
+ if (recordAny.parser_config?.third_party_platform) {
+ baseValues.parser_config.third_party_platform = recordAny.parser_config.third_party_platform;
+ }
+ if (recordAny.parser_config?.yuque_user_id) {
+ baseValues.parser_config.yuque_user_id = recordAny.parser_config.yuque_user_id;
+ }
+ if (recordAny.parser_config?.yuque_token) {
+ baseValues.parser_config.yuque_token = recordAny.parser_config.yuque_token;
+ }
+ if (recordAny.parser_config?.app_id) {
+ baseValues.parser_config.app_id = recordAny.parser_config.app_id;
+ }
+ if (recordAny.parser_config?.app_secret) {
+ baseValues.parser_config.app_secret = recordAny.parser_config.app_secret;
+ }
+ if (recordAny.parser_config?.folder_token) {
+ baseValues.parser_config.folder_token = recordAny.parser_config.folder_token;
+ }
+
+ // Add Web specific fields to parser_config if exists
+ if (recordAny.parser_config?.entry_url) {
+ baseValues.parser_config.entry_url = recordAny.parser_config.entry_url;
+ }
+ if (recordAny.parser_config?.max_pages) {
+ baseValues.parser_config.max_pages = recordAny.parser_config.max_pages;
+ }
+ if (recordAny.parser_config?.delay_seconds) {
+ baseValues.parser_config.delay_seconds = recordAny.parser_config.delay_seconds;
+ }
+ if (recordAny.parser_config?.timeout_seconds) {
+ baseValues.parser_config.timeout_seconds = recordAny.parser_config.timeout_seconds;
+ }
+ if (recordAny.parser_config?.user_agent) {
+ baseValues.parser_config.user_agent = recordAny.parser_config.user_agent;
+ }
+
// If entity_types exists, convert to newline-separated format for TextArea display
if (baseValues.parser_config.graphrag.entity_types) {
if (Array.isArray(baseValues.parser_config.graphrag.entity_types)) {
@@ -255,6 +298,16 @@ const CreateModal = forwardRef(({
setIsRebuildMode(type === 'rebuild'); // Set rebuild mode flag
setOriginalType(type || ''); // Save original type parameter
+ // Set third party platform if editing Third-party type
+ if (actualType === 'Third-party' && record) {
+ const platform = (record as any).parser_config?.third_party_platform;
+ if (platform === 'yuque' || platform === 'feishu') {
+ setThirdPartyPlatform(platform);
+ }
+ } else {
+ setThirdPartyPlatform('yuque'); // Reset to default
+ }
+
// If rebuild mode, default to knowledge graph tab
if (type === 'rebuild') {
setActiveTab('knowledgeGraph');
@@ -319,52 +372,95 @@ const CreateModal = forwardRef(({
}
};
// Actual save logic
- const performSave = () => {
- form
- .validateFields()
- .then(() => {
- setLoading(true)
- const formValues = form.getFieldsValue();
+ const performSave = async () => {
+ try {
+ await form.validateFields();
+ setLoading(true);
+ const formValues = form.getFieldsValue();
+
+ // Check Third-party authentication before saving
+ if (formValues.type === 'Third-party' || currentType === 'Third-party') {
+ const platform = formValues.parser_config?.third_party_platform || thirdPartyPlatform;
- // Process entity_types format conversion: from newline-separated string to string array
- if (formValues.parser_config && formValues.parser_config.graphrag && formValues.parser_config.graphrag.entity_types) {
- const entityTypesString = formValues.parser_config.graphrag.entity_types as any as string;
- const entityTypesArray = entityTypesString
- .split('\n')
- .map((item: string) => item.trim())
- .filter((item: string) => item.length > 0);
- formValues.parser_config.graphrag.entity_types = entityTypesArray;
- }
-
- // Ensure correct type is used when saving (not 'rebuild')
- const saveType = originalType === 'rebuild' ? currentType : (formValues.type || currentType);
-
- const payload: KnowledgeBaseFormData = {
- ...formValues,
- type: saveType,
- permission_id: formValues.permission_id || 'Private',
- parent_id: datasets?.parent_id || undefined,
- };
-
- console.log('Saving payload:', payload); // Debug log
-
- const submit = datasets?.id
- ? updateKnowledgeBase(datasets.id, payload)
- : createKnowledgeBase(payload);
- submit
- .then(() => {
- if (refreshTable) {
- refreshTable();
+ try {
+ if (platform === 'yuque') {
+ // Validate Yuque credentials
+ const yuqueParams = {
+ yuque_user_id: formValues.parser_config?.yuque_user_id,
+ yuque_token: formValues.parser_config?.yuque_token
+ };
+
+ if (!yuqueParams.yuque_user_id || !yuqueParams.yuque_token) {
+ messageApi.error(t('knowledgeBase.yuqueAuthRequired'));
+ setLoading(false);
+ return;
}
- handleClose();
- })
- .catch(() => {
- setLoading(false);
- });
-
- }).catch((err) => {
- console.log('Validation failed:', err)
- });
+
+ await checkYuqueSync(yuqueParams);
+ messageApi.success(t('knowledgeBase.yuqueAuthSuccess'));
+
+ } else if (platform === 'feishu') {
+ // Validate Feishu credentials
+ const feishuParams = {
+ app_id: formValues.parser_config?.app_id,
+ app_secret: formValues.parser_config?.app_secret,
+ folder_token: formValues.parser_config?.folder_token
+ };
+
+ if (!feishuParams.app_id || !feishuParams.app_secret || !feishuParams.folder_token) {
+ messageApi.error(t('knowledgeBase.feishuAuthRequired'));
+ setLoading(false);
+ return;
+ }
+
+ await checkFeishuSync(feishuParams);
+ messageApi.success(t('knowledgeBase.feishuAuthSuccess'));
+ }
+ } catch (error) {
+ console.error('Authentication failed:', error);
+ messageApi.error(t('knowledgeBase.authFailed'));
+ setLoading(false);
+ return;
+ }
+ }
+
+ // Process entity_types format conversion: from newline-separated string to string array
+ if (formValues.parser_config && formValues.parser_config.graphrag && formValues.parser_config.graphrag.entity_types) {
+ const entityTypesString = formValues.parser_config.graphrag.entity_types as any as string;
+ const entityTypesArray = entityTypesString
+ .split('\n')
+ .map((item: string) => item.trim())
+ .filter((item: string) => item.length > 0);
+ formValues.parser_config.graphrag.entity_types = entityTypesArray;
+ }
+
+ // Ensure correct type is used when saving (not 'rebuild')
+ const saveType = originalType === 'rebuild' ? currentType : (formValues.type || currentType);
+
+ const payload: KnowledgeBaseFormData = {
+ ...formValues,
+ type: saveType,
+ permission_id: formValues.permission_id || 'Private',
+ parent_id: datasets?.parent_id || undefined,
+ };
+
+ console.log('Saving payload:', payload); // Debug log
+
+ const submit = datasets?.id
+ ? updateKnowledgeBase(datasets.id, payload)
+ : createKnowledgeBase(payload);
+
+ await submit;
+
+ if (refreshTable) {
+ refreshTable();
+ }
+ handleClose();
+
+ } catch (err) {
+ console.log('Validation or save failed:', err);
+ setLoading(false);
+ }
}
const handleChange = (_value: string, tp: string) => {
// Only trigger prompt in edit mode and when type is embedding
@@ -424,6 +520,139 @@ const CreateModal = forwardRef(({
+ {/* Web type specific fields */}
+ {currentType === 'Web' && (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )}
+
+ {/* Third-party type specific fields */}
+ {currentType === 'Third-party' && (
+ <>
+
+
+
+ {thirdPartyPlatform === 'yuque' && (
+ <>
+
+
+
+
+
+
+
+ >
+ )}
+
+ {thirdPartyPlatform === 'feishu' && (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )}
+ >
+ )}
+
{currentType !== 'Folder' && dynamicTypeList.map((tp) => {
const fieldKey = typeToFieldKey(tp);
// When tp is 'llm', merge llm and chat options
diff --git a/web/src/views/KnowledgeBase/index.tsx b/web/src/views/KnowledgeBase/index.tsx
index b8bd0acd..75a23bbd 100644
--- a/web/src/views/KnowledgeBase/index.tsx
+++ b/web/src/views/KnowledgeBase/index.tsx
@@ -223,8 +223,6 @@ const KnowledgeBaseManagement: FC = () => {
const fetchKnowledgeBaseTypes = async () => {
try {
let types = await getKnowledgeBaseTypeList();
- types = types.filter(type => (type === 'General' || type === 'Folder' )); //
- //暂时未实现 ,过滤掉未实现
setKnowledgeBaseTypes(types);
} catch (error) {
console.error('Failed to fetch knowledge base types:', error);
diff --git a/web/src/views/KnowledgeBase/types.ts b/web/src/views/KnowledgeBase/types.ts
index c9135029..95fa5b90 100644
--- a/web/src/views/KnowledgeBase/types.ts
+++ b/web/src/views/KnowledgeBase/types.ts
@@ -95,8 +95,24 @@ export interface ParserConfig {
auto_keywords?: number; // 自动关键词
auto_questions?: number; // 自动问题
html4excel?: boolean; // 是否为Excel文件
- graphrag:GraphragConfig; // 知识图谱生成
-
+ graphrag: GraphragConfig; // 知识图谱生成
+
+ // Web 类型特有字段
+ entry_url?: string; // 入口网址
+ max_pages?: number; // 最大页面数 (10-200)
+ delay_seconds?: number; // 延迟秒数 (1-3)
+ timeout_seconds?: number; // 超时秒数 (5-15)
+ user_agent?: string; // 用户代理
+
+ // Third-party 类型特有字段
+ third_party_platform?: 'yuque' | 'feishu'; // 第三方平台类型
+ // 语雀字段
+ yuque_user_id?: string; // 语雀用户ID
+ yuque_token?: string; // 语雀Token
+ // 飞书字段
+ app_id?: string; // 飞书应用ID
+ app_secret?: string; // 飞书应用密钥
+ folder_token?: string; // 飞书文件夹Token
}
// 文件数据
export interface KnowledgeBaseDocumentData { // 知识库文档数据