feat(web): refactor knowledge base form state management and field synchronization
- Add Form.useWatch hook to monitor _third_party_platform field changes directly - Implement useEffect to sync form value to thirdPartyPlatform state when platform changes - Remove redundant conditional field assignments for third-party and web parser configs - Consolidate third-party platform state initialization in setBaseFields function - Update Feishu parameter naming from generic (app_id, app_secret, folder_token) to prefixed format (feishu_app_id, feishu_app_secret, feishu_folder_token) - Rename third_party_platform field to _third_party_platform for consistency - Optimize useEffect dependencies to prevent unnecessary re-renders and state inconsistencies - Improve form field initialization logic to handle both create and edit modes correctly - Simplify third-party platform state management by centralizing it in setBaseFields instead of multiple locations
This commit is contained in:
@@ -47,6 +47,16 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
const entityNormalization = graphragConfig?.resolution || false;
|
const entityNormalization = graphragConfig?.resolution || false;
|
||||||
const communityReportGeneration = graphragConfig?.community || false;
|
const communityReportGeneration = graphragConfig?.community || false;
|
||||||
|
|
||||||
|
// Watch for changes to _third_party_platform field directly
|
||||||
|
const formThirdPartyPlatform = Form.useWatch(['parser_config', '_third_party_platform'], form);
|
||||||
|
|
||||||
|
// Sync form value to state when form value changes
|
||||||
|
useEffect(() => {
|
||||||
|
if (formThirdPartyPlatform && (formThirdPartyPlatform === 'yuque' || formThirdPartyPlatform === 'feishu')) {
|
||||||
|
setThirdPartyPlatform(formThirdPartyPlatform);
|
||||||
|
}
|
||||||
|
}, [formThirdPartyPlatform]);
|
||||||
|
|
||||||
// Encapsulate cancel method, add close modal logic
|
// Encapsulate cancel method, add close modal logic
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
setDatasets(null);
|
setDatasets(null);
|
||||||
@@ -199,6 +209,8 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
type: type || currentType,
|
type: type || currentType,
|
||||||
};
|
};
|
||||||
form.setFieldsValue(defaults);
|
form.setFieldsValue(defaults);
|
||||||
|
// Reset third party platform to default when creating new
|
||||||
|
setThirdPartyPlatform('yuque');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const baseValues: Partial<KnowledgeBaseFormData> = {
|
const baseValues: Partial<KnowledgeBaseFormData> = {
|
||||||
@@ -210,7 +222,6 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Process parser_config data, set default values if not present
|
// Process parser_config data, set default values if not present
|
||||||
const recordAny = record as any;
|
|
||||||
baseValues.parser_config = {
|
baseValues.parser_config = {
|
||||||
...record.parser_config,
|
...record.parser_config,
|
||||||
graphrag: {
|
graphrag: {
|
||||||
@@ -224,43 +235,6 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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 entity_types exists, convert to newline-separated format for TextArea display
|
||||||
if (baseValues.parser_config.graphrag.entity_types) {
|
if (baseValues.parser_config.graphrag.entity_types) {
|
||||||
if (Array.isArray(baseValues.parser_config.graphrag.entity_types)) {
|
if (Array.isArray(baseValues.parser_config.graphrag.entity_types)) {
|
||||||
@@ -272,7 +246,18 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set form values first
|
||||||
form.setFieldsValue(baseValues);
|
form.setFieldsValue(baseValues);
|
||||||
|
|
||||||
|
// Then sync third party platform state from form value
|
||||||
|
// This ensures the state matches what's actually in the form
|
||||||
|
const platform = baseValues.parser_config?._third_party_platform;
|
||||||
|
if (platform === 'yuque' || platform === 'feishu') {
|
||||||
|
setThirdPartyPlatform(platform);
|
||||||
|
} else {
|
||||||
|
// Reset to default if no platform specified
|
||||||
|
setThirdPartyPlatform('yuque');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setDynamicModelFields = (record: KnowledgeBaseListItem | null, types: string[]) => {
|
const setDynamicModelFields = (record: KnowledgeBaseListItem | null, types: string[]) => {
|
||||||
@@ -295,20 +280,17 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
setDatasets(record || null);
|
setDatasets(record || null);
|
||||||
|
|
||||||
// If rebuild mode, use record's actual type, otherwise use passed type
|
// If rebuild mode, use record's actual type, otherwise use passed type
|
||||||
const actualType = type === 'rebuild' ? (record?.type || 'General') : (type || currentType);
|
// If editing (record exists but no type passed), use record's type
|
||||||
|
const actualType = type === 'rebuild'
|
||||||
|
? (record?.type || 'General')
|
||||||
|
: (type || record?.type || currentType);
|
||||||
|
|
||||||
setCurrentType(actualType as any);
|
setCurrentType(actualType as any);
|
||||||
setIsRebuildMode(type === 'rebuild'); // Set rebuild mode flag
|
setIsRebuildMode(type === 'rebuild'); // Set rebuild mode flag
|
||||||
setOriginalType(type || ''); // Save original type parameter
|
setOriginalType(type || ''); // Save original type parameter
|
||||||
|
|
||||||
// Set third party platform if editing Third-party type
|
// Note: third party platform state will be set in setBaseFields function
|
||||||
if (actualType === 'Third-party' && record) {
|
// No need to set it here separately to avoid inconsistency
|
||||||
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 rebuild mode, default to knowledge graph tab
|
||||||
if (type === 'rebuild') {
|
if (type === 'rebuild') {
|
||||||
@@ -336,9 +318,13 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!visible) return;
|
if (!visible) return;
|
||||||
setBaseFields(datasets, currentType);
|
// Only set fields when modal becomes visible, not on every state change
|
||||||
setDynamicModelFields(datasets, modelTypeList);
|
// setBaseFields is already called in handleOpen
|
||||||
}, [visible, datasets, currentType, modelTypeList]);
|
// This useEffect is mainly for syncing dynamic model fields
|
||||||
|
if (datasets && modelTypeList.length > 0) {
|
||||||
|
setDynamicModelFields(datasets, modelTypeList);
|
||||||
|
}
|
||||||
|
}, [visible, modelTypeList]);
|
||||||
|
|
||||||
// Encapsulate save method, add submit logic
|
// Encapsulate save method, add submit logic
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
@@ -382,7 +368,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
|
|
||||||
// Check Third-party authentication before saving
|
// Check Third-party authentication before saving
|
||||||
if (formValues.type === 'Third-party' || currentType === 'Third-party') {
|
if (formValues.type === 'Third-party' || currentType === 'Third-party') {
|
||||||
const platform = formValues.parser_config?.third_party_platform || thirdPartyPlatform;
|
const platform = formValues.parser_config?._third_party_platform || thirdPartyPlatform;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (platform === 'yuque') {
|
if (platform === 'yuque') {
|
||||||
@@ -404,9 +390,9 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
} else if (platform === 'feishu') {
|
} else if (platform === 'feishu') {
|
||||||
// Validate Feishu credentials
|
// Validate Feishu credentials
|
||||||
const feishuParams = {
|
const feishuParams = {
|
||||||
feishu_app_id: formValues.parser_config?.app_id,
|
feishu_app_id: formValues.parser_config?.feishu_app_id,
|
||||||
feishu_app_secret: formValues.parser_config?.app_secret,
|
feishu_app_secret: formValues.parser_config?.feishu_app_secret,
|
||||||
feishu_folder_token: formValues.parser_config?.folder_token
|
feishu_folder_token: formValues.parser_config?.feishu_folder_token
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!feishuParams.feishu_app_id || !feishuParams.feishu_app_secret || !feishuParams.feishu_folder_token) {
|
if (!feishuParams.feishu_app_id || !feishuParams.feishu_app_secret || !feishuParams.feishu_folder_token) {
|
||||||
@@ -533,7 +519,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
{ type: 'url', message: t('knowledgeBase.createForm.entryUrlInvalid') }
|
{ type: 'url', message: t('knowledgeBase.createForm.entryUrlInvalid') }
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input placeholder="https://ai.redbearai.com" />
|
<Input placeholder="https://ai.redbearai.com" disabled={!!datasets?.id} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@@ -545,7 +531,8 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
<SliderInput
|
<SliderInput
|
||||||
min={10}
|
min={10}
|
||||||
max={200}
|
max={200}
|
||||||
step={1}
|
step={10}
|
||||||
|
disabled={!!datasets?.id}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
@@ -553,12 +540,13 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
name={['parser_config', 'delay_seconds']}
|
name={['parser_config', 'delay_seconds']}
|
||||||
label={t('knowledgeBase.createForm.delaySeconds')}
|
label={t('knowledgeBase.createForm.delaySeconds')}
|
||||||
rules={[{ required: true, message: t('knowledgeBase.createForm.delaySecondsRequired') }]}
|
rules={[{ required: true, message: t('knowledgeBase.createForm.delaySecondsRequired') }]}
|
||||||
initialValue={1.0}
|
initialValue={2}
|
||||||
>
|
>
|
||||||
<SliderInput
|
<SliderInput
|
||||||
min={1}
|
min={1}
|
||||||
max={3}
|
max={3}
|
||||||
step={0.1}
|
step={1}
|
||||||
|
disabled={!!datasets?.id}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
@@ -572,6 +560,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
min={5}
|
min={5}
|
||||||
max={15}
|
max={15}
|
||||||
step={1}
|
step={1}
|
||||||
|
disabled={!!datasets?.id}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
@@ -581,7 +570,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
rules={[{ required: true, message: t('knowledgeBase.createForm.userAgentRequired') }]}
|
rules={[{ required: true, message: t('knowledgeBase.createForm.userAgentRequired') }]}
|
||||||
initialValue="KnowledgeBaseCrawler/1.0"
|
initialValue="KnowledgeBaseCrawler/1.0"
|
||||||
>
|
>
|
||||||
<Input placeholder="KnowledgeBaseCrawler/1.0" />
|
<Input placeholder="KnowledgeBaseCrawler/1.0" disabled={!!datasets?.id} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@@ -596,8 +585,8 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
initialValue="yuque"
|
initialValue="yuque"
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
value={thirdPartyPlatform}
|
|
||||||
onChange={(value) => setThirdPartyPlatform(value)}
|
onChange={(value) => setThirdPartyPlatform(value)}
|
||||||
|
disabled={!!datasets?.id}
|
||||||
options={[
|
options={[
|
||||||
{ value: 'yuque', label: t('knowledgeBase.createForm.yuque') },
|
{ value: 'yuque', label: t('knowledgeBase.createForm.yuque') },
|
||||||
{ value: 'feishu', label: t('knowledgeBase.createForm.feishu') }
|
{ value: 'feishu', label: t('knowledgeBase.createForm.feishu') }
|
||||||
@@ -612,7 +601,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
label={t('knowledgeBase.createForm.yuqueUserId')}
|
label={t('knowledgeBase.createForm.yuqueUserId')}
|
||||||
rules={[{ required: true, message: t('knowledgeBase.createForm.yuqueUserIdRequired') }]}
|
rules={[{ required: true, message: t('knowledgeBase.createForm.yuqueUserIdRequired') }]}
|
||||||
>
|
>
|
||||||
<Input placeholder={t('knowledgeBase.createForm.yuqueUserIdPlaceholder')} />
|
<Input placeholder={t('knowledgeBase.createForm.yuqueUserIdPlaceholder')} disabled={!!datasets?.id} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@@ -620,7 +609,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
label={t('knowledgeBase.createForm.yuqueToken')}
|
label={t('knowledgeBase.createForm.yuqueToken')}
|
||||||
rules={[{ required: true, message: t('knowledgeBase.createForm.yuqueTokenRequired') }]}
|
rules={[{ required: true, message: t('knowledgeBase.createForm.yuqueTokenRequired') }]}
|
||||||
>
|
>
|
||||||
<Input.Password placeholder={t('knowledgeBase.createForm.yuqueTokenPlaceholder')} />
|
<Input.Password placeholder={t('knowledgeBase.createForm.yuqueTokenPlaceholder')} disabled={!!datasets?.id} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@@ -632,23 +621,23 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
|||||||
label={t('knowledgeBase.createForm.feishuAppId')}
|
label={t('knowledgeBase.createForm.feishuAppId')}
|
||||||
rules={[{ required: true, message: t('knowledgeBase.createForm.feishuAppIdRequired') }]}
|
rules={[{ required: true, message: t('knowledgeBase.createForm.feishuAppIdRequired') }]}
|
||||||
>
|
>
|
||||||
<Input placeholder={t('knowledgeBase.createForm.feishuAppIdPlaceholder')} />
|
<Input placeholder={t('knowledgeBase.createForm.feishuAppIdPlaceholder')} disabled={!!datasets?.id} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name={['parser_config', 'app_secret']}
|
name={['parser_config', 'feishu_app_secret']}
|
||||||
label={t('knowledgeBase.createForm.feishuAppSecret')}
|
label={t('knowledgeBase.createForm.feishuAppSecret')}
|
||||||
rules={[{ required: true, message: t('knowledgeBase.createForm.feishuAppSecretRequired') }]}
|
rules={[{ required: true, message: t('knowledgeBase.createForm.feishuAppSecretRequired') }]}
|
||||||
>
|
>
|
||||||
<Input.Password placeholder={t('knowledgeBase.createForm.feishuAppSecretPlaceholder')} />
|
<Input.Password placeholder={t('knowledgeBase.createForm.feishuAppSecretPlaceholder')} disabled={!!datasets?.id} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name={['parser_config', 'folder_token']}
|
name={['parser_config', 'feishu_folder_token']}
|
||||||
label={t('knowledgeBase.createForm.feishuFolderToken')}
|
label={t('knowledgeBase.createForm.feishuFolderToken')}
|
||||||
rules={[{ required: true, message: t('knowledgeBase.createForm.feishuFolderTokenRequired') }]}
|
rules={[{ required: true, message: t('knowledgeBase.createForm.feishuFolderTokenRequired') }]}
|
||||||
>
|
>
|
||||||
<Input placeholder={t('knowledgeBase.createForm.feishuFolderTokenPlaceholder')} />
|
<Input placeholder={t('knowledgeBase.createForm.feishuFolderTokenPlaceholder')} disabled={!!datasets?.id} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -100,6 +100,20 @@ const RecallTestResult = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Show skeleton when initial loading
|
||||||
|
if (loading && data.length === 0) {
|
||||||
|
return (
|
||||||
|
<div className='rb:flex rb:flex-col'>
|
||||||
|
<div className='rb:flex rb:items-center rb:justify-start rb:gap-2 rb:mb-4'>
|
||||||
|
<span className='rb:text-lg rb:font-medium'>{t('knowledgeBase.recallResult')}</span>
|
||||||
|
</div>
|
||||||
|
<Skeleton active paragraph={{ rows: 3 }} />
|
||||||
|
<Skeleton active paragraph={{ rows: 3 }} className='rb:mt-4' />
|
||||||
|
<Skeleton active paragraph={{ rows: 3 }} className='rb:mt-4' />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (data.length === 0 && showEmpty) {
|
if (data.length === 0 && showEmpty) {
|
||||||
return (
|
return (
|
||||||
<NoData
|
<NoData
|
||||||
|
|||||||
@@ -105,14 +105,14 @@ export interface ParserConfig {
|
|||||||
user_agent?: string; // 用户代理
|
user_agent?: string; // 用户代理
|
||||||
|
|
||||||
// Third-party 类型特有字段
|
// Third-party 类型特有字段
|
||||||
third_party_platform?: 'yuque' | 'feishu'; // 第三方平台类型
|
_third_party_platform?: 'yuque' | 'feishu'; // 第三方平台类型
|
||||||
// 语雀字段
|
// 语雀字段
|
||||||
yuque_user_id?: string; // 语雀用户ID
|
yuque_user_id?: string; // 语雀用户ID
|
||||||
yuque_token?: string; // 语雀Token
|
yuque_token?: string; // 语雀Token
|
||||||
// 飞书字段
|
// 飞书字段
|
||||||
app_id?: string; // 飞书应用ID
|
feishu_app_id?: string; // 飞书应用ID
|
||||||
app_secret?: string; // 飞书应用密钥
|
feishu_app_secret?: string; // 飞书应用密钥
|
||||||
folder_token?: string; // 飞书文件夹Token
|
feishu_folder_token?: string; // 飞书文件夹Token
|
||||||
}
|
}
|
||||||
// 文件数据
|
// 文件数据
|
||||||
export interface KnowledgeBaseDocumentData { // 知识库文档数据
|
export interface KnowledgeBaseDocumentData { // 知识库文档数据
|
||||||
|
|||||||
Reference in New Issue
Block a user