2025-11-07 13:30:59 +08:00
|
|
|
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
|
|
|
|
import {
|
|
|
|
|
|
Dialog,
|
|
|
|
|
|
DialogTitle,
|
|
|
|
|
|
DialogContent,
|
|
|
|
|
|
DialogActions,
|
|
|
|
|
|
Button,
|
|
|
|
|
|
Box,
|
|
|
|
|
|
Divider,
|
|
|
|
|
|
} from '@mui/material';
|
|
|
|
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
|
|
import { useForm, FormProvider } from 'react-hook-form';
|
|
|
|
|
|
import GeneralForm from './GeneralForm';
|
|
|
|
|
|
import { RadioFormField } from '@/components/FormField';
|
|
|
|
|
|
import { ChunkMethodItem, PipelineSelectorItem } from '../configuration';
|
2025-11-07 17:49:44 +08:00
|
|
|
|
import { DocumentParserType, ParseType } from '@/constants/knowledge';
|
2025-11-07 13:30:59 +08:00
|
|
|
|
import { useKnowledgeOperations } from '@/hooks/knowledge-hooks';
|
|
|
|
|
|
import { useSnackbar } from '@/components/Provider/SnackbarProvider';
|
|
|
|
|
|
|
|
|
|
|
|
export interface CreateKnowledgeDialogProps {
|
|
|
|
|
|
open: boolean;
|
|
|
|
|
|
onClose: () => void;
|
|
|
|
|
|
onSuccess?: () => void;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function CreateKnowledgeDialog({ open, onClose, onSuccess }: CreateKnowledgeDialogProps) {
|
|
|
|
|
|
const { t } = useTranslation();
|
|
|
|
|
|
const { showMessage } = useSnackbar();
|
|
|
|
|
|
const { createKnowledge, loading, clearError } = useKnowledgeOperations();
|
|
|
|
|
|
|
|
|
|
|
|
// 表单实例与默认值
|
|
|
|
|
|
const form = useForm<any>({
|
|
|
|
|
|
defaultValues: {
|
|
|
|
|
|
name: '',
|
|
|
|
|
|
description: '',
|
|
|
|
|
|
permission: 'me',
|
|
|
|
|
|
avatar: undefined,
|
|
|
|
|
|
pagerank: 0,
|
|
|
|
|
|
embd_id: '',
|
|
|
|
|
|
// 解析相关
|
2025-11-07 17:49:44 +08:00
|
|
|
|
parser_id: DocumentParserType.Naive,
|
2025-11-07 13:30:59 +08:00
|
|
|
|
pipeline_id: '',
|
|
|
|
|
|
parseType: ParseType.BuildIn,
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const [parseType, setParseType] = useState<ParseType>(ParseType.BuildIn);
|
|
|
|
|
|
|
|
|
|
|
|
// 同步 parseType 到表单并清理互斥字段
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
form.setValue('parseType', parseType);
|
|
|
|
|
|
if (parseType === ParseType.BuildIn) {
|
|
|
|
|
|
// 选择内置解析时清空 pipeline_id
|
|
|
|
|
|
form.setValue('pipeline_id', '');
|
|
|
|
|
|
}
|
|
|
|
|
|
}, [parseType]);
|
|
|
|
|
|
|
|
|
|
|
|
const handleSubmit = async (data: any) => {
|
|
|
|
|
|
clearError();
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 构建创建数据(basicData + 解析选择)
|
|
|
|
|
|
const requestData = {
|
|
|
|
|
|
name: data.name,
|
|
|
|
|
|
description: data.description,
|
|
|
|
|
|
permission: data.permission,
|
|
|
|
|
|
avatar: data.avatar,
|
|
|
|
|
|
pagerank: data.pagerank,
|
|
|
|
|
|
embd_id: data.embd_id,
|
|
|
|
|
|
// 解析相关字段:后端已支持 parser_id / pipeline_id
|
|
|
|
|
|
parser_id: data.parser_id,
|
|
|
|
|
|
pipeline_id: data.pipeline_id,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
await createKnowledge(requestData);
|
|
|
|
|
|
showMessage.success(t('knowledgeConfiguration.createSuccess'));
|
|
|
|
|
|
onSuccess?.();
|
|
|
|
|
|
onClose();
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
// 错误提示由 hook 内部处理,这里保底提示
|
|
|
|
|
|
showMessage.error(t('knowledgeConfiguration.createFailed'));
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleCancel = () => {
|
|
|
|
|
|
onClose();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<Dialog open={open} onClose={onClose} maxWidth="md" fullWidth>
|
|
|
|
|
|
<DialogTitle>{t('knowledgeList.createKnowledgeBase')}</DialogTitle>
|
|
|
|
|
|
<FormProvider {...form}>
|
|
|
|
|
|
<DialogContent>
|
|
|
|
|
|
{/* 基础信息表单(名称、描述、权限、头像、嵌入模型、Pagerank 等) */}
|
|
|
|
|
|
<GeneralForm />
|
|
|
|
|
|
|
|
|
|
|
|
<Divider sx={{ my: 2 }} />
|
|
|
|
|
|
|
|
|
|
|
|
{/* 解析方式选择与联动(来自 ChunkMethodForm) */}
|
|
|
|
|
|
<Box sx={{ px: 1 }}>
|
|
|
|
|
|
<RadioFormField
|
|
|
|
|
|
name="parseType"
|
|
|
|
|
|
label={t('knowledgeConfiguration.parseType')}
|
|
|
|
|
|
defaultValue={parseType}
|
|
|
|
|
|
options={[
|
|
|
|
|
|
{ value: ParseType.BuildIn, label: 'Built-in' },
|
|
|
|
|
|
{ value: ParseType.Pipeline, label: 'Pipeline' },
|
|
|
|
|
|
]}
|
|
|
|
|
|
onChangeValue={(v) => setParseType(v as ParseType)}
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 基于模式:内置显示切片方法,Pipeline 显示选择器 */}
|
|
|
|
|
|
<Box sx={{ mt: 2 }}>
|
|
|
|
|
|
{parseType === ParseType.BuildIn ? (
|
|
|
|
|
|
<ChunkMethodItem />
|
|
|
|
|
|
) : (
|
|
|
|
|
|
<PipelineSelectorItem />
|
|
|
|
|
|
)}
|
|
|
|
|
|
</Box>
|
|
|
|
|
|
</Box>
|
|
|
|
|
|
</DialogContent>
|
|
|
|
|
|
</FormProvider>
|
|
|
|
|
|
<DialogActions>
|
|
|
|
|
|
<Button onClick={handleCancel} disabled={loading}>{t('common.cancel')}</Button>
|
|
|
|
|
|
<Button onClick={form.handleSubmit(handleSubmit)} variant="contained" disabled={loading}>
|
|
|
|
|
|
{loading ? t('knowledgeConfiguration.creating') : t('knowledgeConfiguration.createAndNext')}
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</DialogActions>
|
|
|
|
|
|
</Dialog>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export default CreateKnowledgeDialog;
|