接近完美版本

This commit is contained in:
2025-04-10 10:16:15 +08:00
parent 80a6764ba0
commit 8be2fd5d67
2 changed files with 279 additions and 240 deletions
+148 -179
View File
@@ -87,8 +87,153 @@ export function ReviewSettings({
// 使用useRef跟踪是否已经初始化过 // 使用useRef跟踪是否已经初始化过
const initializedRef = useRef(false); const initializedRef = useRef(false);
// 保存初始数据的引用,用于检测是否有实际变更 // 保存初始数据的引用,用于检测是否有实际变更
const initialDataRef = useRef<any>(null); const initialDataRef = useRef<ReviewSettingsProps['initialData'] | null>(null);
// 生成评查配置并发送给父组件
const generateEvaluationConfig = useCallback(() => {
// 构建评查配置对象
const evaluationConfig = {
logicType: combinationLogic,
customLogic: customLogic,
rules: rules
.filter(rule => rule.type) // 过滤掉没有选择类型的规则
.map(rule => {
// 处理不同规则类型的特殊配置
const processedConfig = { ...rule.config };
switch(rule.type) {
case 'exists':
// 确保fields字段是数组
if (!Array.isArray(processedConfig.fields)) {
processedConfig.fields = [];
}
// 确保logic字段有值
if (!processedConfig.logic) {
processedConfig.logic = 'and';
}
break;
case 'consistency':
// 确保pairs字段是数组
if (!Array.isArray(processedConfig.pairs)) {
processedConfig.pairs = [];
}
// 确保logic字段有值
if (!processedConfig.logic) {
processedConfig.logic = 'and';
}
break;
case 'format':
// 确保field字段正确设置
if (processedConfig.checkField) {
processedConfig.field = processedConfig.checkField;
delete processedConfig.checkField;
}
// 确保field字段有值
if (!processedConfig.field) {
processedConfig.field = '';
}
if (processedConfig.formatParams) {
processedConfig.parameters = processedConfig.formatParams;
delete processedConfig.formatParams;
}
// 确保formatType字段有值
if (!processedConfig.formatType) {
processedConfig.formatType = '';
}
// 确保parameters字段有值
if (!processedConfig.parameters) {
processedConfig.parameters = '';
}
break;
case 'regex':
// 确保field和pattern字段正确设置
if (processedConfig.checkField) {
processedConfig.field = processedConfig.checkField;
delete processedConfig.checkField;
}
// 确保field字段有值
if (!processedConfig.field) {
processedConfig.field = '';
}
if (processedConfig.regexPattern) {
processedConfig.pattern = processedConfig.regexPattern;
delete processedConfig.regexPattern;
}
// 确保pattern字段有值
if (!processedConfig.pattern) {
processedConfig.pattern = '';
}
// 确保matchType字段有值
if (!processedConfig.matchType) {
processedConfig.matchType = 'match';
}
break;
case 'ai':
// 确保model字段有值
if (!processedConfig.model) {
processedConfig.model = 'qwen14b';
}
// 确保temperature字段是数字
if (typeof processedConfig.temperature !== 'number') {
processedConfig.temperature = 0.1;
}
// 确保prompt字段有值
if (!processedConfig.prompt) {
processedConfig.prompt = '';
}
break;
case 'code':
// 确保language字段有值
if (!processedConfig.language) {
processedConfig.language = 'javascript';
}
// 确保code字段有值
if (!processedConfig.code) {
processedConfig.code = '';
}
break;
}
// 移除辅助用的UI字段
delete processedConfig.availableFields;
return {
id: rule.id,
type: rule.type,
config: processedConfig
};
})
};
// 使用setTimeout避免连锁更新
setTimeout(() => {
if (onChange) {
// 仅将一个evaluation_config对象传递给父组件
onChange({ evaluation_config: evaluationConfig });
}
}, 0);
return evaluationConfig;
}, [rules, combinationLogic, customLogic, onChange]);
// 加载初始数据 // 加载初始数据
useEffect(() => { useEffect(() => {
// 如果已经初始化过,则跳过此次处理 // 如果已经初始化过,则跳过此次处理
@@ -200,7 +345,7 @@ export function ReviewSettings({
}, 0); }, 0);
} }
// 移除availableFields依赖,避免死循环 // 移除availableFields依赖,避免死循环
}, [initialData]); }, [initialData, availableFields, generateEvaluationConfig]);
// 监听extractionFields的变化 // 监听extractionFields的变化
useEffect(() => { useEffect(() => {
@@ -271,7 +416,7 @@ export function ReviewSettings({
useEffect(() => { useEffect(() => {
// 生成并更新评查配置 // 生成并更新评查配置
generateEvaluationConfig(); generateEvaluationConfig();
}, []); }, [generateEvaluationConfig]);
// 处理已删除字段的函数 // 处理已删除字段的函数
const handleDeletedFields = (deletedFields: string[]) => { const handleDeletedFields = (deletedFields: string[]) => {
@@ -1528,182 +1673,6 @@ export function ReviewSettings({
} }
}; };
// 生成完整的评查配置数据并在提交保存时使用
const generateEvaluationConfig = useCallback(() => {
// 创建符合数据库模式的evaluation_config对象
const evaluationConfig = {
logicType: combinationLogic || 'and',
customLogic: combinationLogic === 'custom' ? (customLogic || '') : '',
rules: rules
.filter(rule => rule.type && rule.type.trim() !== '')
.map(rule => {
// 创建一个深拷贝以避免修改原始对象
const processedConfig = JSON.parse(JSON.stringify(rule.config || {}));
// 根据规则类型处理特定的字段映射
switch(rule.type) {
case 'exists':
// 将UI字段名映射为API字段名
if (Array.isArray(processedConfig.selectedFields)) {
processedConfig.fields = processedConfig.selectedFields;
delete processedConfig.selectedFields;
}
// 确保fields字段存在且是数组
if (!Array.isArray(processedConfig.fields)) {
processedConfig.fields = [];
}
if (processedConfig.existsLogic) {
processedConfig.logic = processedConfig.existsLogic;
delete processedConfig.existsLogic;
}
// 确保logic字段有默认值
if (!processedConfig.logic) {
processedConfig.logic = 'and';
}
break;
case 'consistency':
case 'logic':
// 将UI字段名映射为API字段名
if (processedConfig.logicRelation) {
processedConfig.logic = processedConfig.logicRelation;
delete processedConfig.logicRelation;
}
// 确保logic字段有默认值
if (!processedConfig.logic) {
processedConfig.logic = 'and';
}
// 确保pairs/conditions字段是数组
if (rule.type === 'consistency' && !Array.isArray(processedConfig.pairs)) {
processedConfig.pairs = [];
}
if (rule.type === 'logic' && !Array.isArray(processedConfig.conditions)) {
processedConfig.conditions = [];
}
// 删除用于UI的临时字段
delete processedConfig.initialSourceField;
delete processedConfig.initialTargetField;
delete processedConfig.initialCompareMethod;
delete processedConfig.initialField;
delete processedConfig.initialOperator;
delete processedConfig.initialValue;
break;
case 'format':
// 确保field字段正确设置
if (processedConfig.checkField) {
processedConfig.field = processedConfig.checkField;
delete processedConfig.checkField;
}
// 确保field字段有值
if (!processedConfig.field) {
processedConfig.field = '';
}
if (processedConfig.formatParams) {
processedConfig.parameters = processedConfig.formatParams;
delete processedConfig.formatParams;
}
// 确保formatType字段有值
if (!processedConfig.formatType) {
processedConfig.formatType = '';
}
// 确保parameters字段有值
if (!processedConfig.parameters) {
processedConfig.parameters = '';
}
break;
case 'regex':
// 确保field和pattern字段正确设置
if (processedConfig.checkField) {
processedConfig.field = processedConfig.checkField;
delete processedConfig.checkField;
}
// 确保field字段有值
if (!processedConfig.field) {
processedConfig.field = '';
}
if (processedConfig.regexPattern) {
processedConfig.pattern = processedConfig.regexPattern;
delete processedConfig.regexPattern;
}
// 确保pattern字段有值
if (!processedConfig.pattern) {
processedConfig.pattern = '';
}
// 确保matchType字段有值
if (!processedConfig.matchType) {
processedConfig.matchType = 'match';
}
break;
case 'ai':
// 确保model字段有值
if (!processedConfig.model) {
processedConfig.model = 'qwen14b';
}
// 确保temperature字段是数字
if (typeof processedConfig.temperature !== 'number') {
processedConfig.temperature = 0.1;
}
// 确保prompt字段有值
if (!processedConfig.prompt) {
processedConfig.prompt = '';
}
break;
case 'code':
// 确保language字段有值
if (!processedConfig.language) {
processedConfig.language = 'javascript';
}
// 确保code字段有值
if (!processedConfig.code) {
processedConfig.code = '';
}
break;
}
// 移除辅助用的UI字段
delete processedConfig.availableFields;
return {
id: rule.id,
type: rule.type,
config: processedConfig
};
})
};
// 使用setTimeout避免连锁更新
setTimeout(() => {
if (onChange) {
// 仅将一个evaluation_config对象传递给父组件
onChange({ evaluation_config: evaluationConfig });
}
}, 0);
return evaluationConfig;
}, [rules, combinationLogic, customLogic, onChange]);
// 组件初次渲染后,主动发送一次完整配置数据 // 组件初次渲染后,主动发送一次完整配置数据
useEffect(() => { useEffect(() => {
// 如果有初始数据,在组件挂载后主动发送一次完整规则配置 // 如果有初始数据,在组件挂载后主动发送一次完整规则配置
+131 -61
View File
@@ -135,6 +135,7 @@ export default function RuleNew() {
const location = useLocation(); const location = useLocation();
const [isEditMode, setIsEditMode] = useState(false); const [isEditMode, setIsEditMode] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [instanceKey, setInstanceKey] = useState<string>('new');
const [formData, setFormData] = useState<EvaluationPoint>({}); const [formData, setFormData] = useState<EvaluationPoint>({});
const [evaluationPointGroups, setEvaluationPointGroups] = useState<EvaluationPointGroup[]>([]); const [evaluationPointGroups, setEvaluationPointGroups] = useState<EvaluationPointGroup[]>([]);
@@ -174,6 +175,57 @@ export default function RuleNew() {
return fields; return fields;
}, []); }, []);
/**
* 重置表单数据到默认状态
*/
const resetFormData = useCallback(() => {
console.log("重置表单数据到默认状态");
setFormData({
name: '',
code: '',
risk: 'low',
is_enabled: true,
description: '',
references_laws: { name: '', articles: [], content: '' },
evaluation_point_groups_pid: null,
evaluation_point_groups_id: null,
extraction_config: {
llm: {
fields: [],
prompt_setting: {
type: 'system',
template: ''
}
},
vlm: {
fields: [],
prompt_setting: {
type: 'system',
template: ''
}
},
regex: {
fields: []
}
},
evaluation_config: {
logicType: 'and',
customLogic: '',
rules: []
},
pass_message: '文档检查通过,符合规范要求。',
fail_message: '文档存在以下问题,请修改后重新提交。',
suggestion_message: '',
suggestion_message_type: 'warning',
post_action: 'none',
action_config: '',
score: 0
});
setExtractionFields([]);
// 生成新的实例键,强制所有子组件重新渲染
setInstanceKey(`new_${Date.now()}`);
}, []);
/** /**
* 获取评查点数据 * 获取评查点数据
* 编辑模式下从API获取指定ID的评查点数据 * 编辑模式下从API获取指定ID的评查点数据
@@ -193,23 +245,34 @@ export default function RuleNew() {
console.log(response); console.log(response);
if (response.ok) { if (response.ok) {
const data = await response.json(); const data = await response.json();
setFormData(data.data[0]); if (data.data && data.data[0]) {
setFormData(data.data[0]);
// 初始化extractionFields
if (data.data[0]) { // 初始化extractionFields
const extractedFields = extractFieldsFromFormData(data.data[0]); const extractedFields = extractFieldsFromFormData(data.data[0]);
setExtractionFields(extractedFields); setExtractionFields(extractedFields);
// 设置编辑模式的实例键
setInstanceKey(`edit_${id}_${Date.now()}`);
} else {
console.error('获取数据失败: 返回数据为空');
alert('获取数据失败: 返回数据为空');
resetFormData();
navigate('/rules');
} }
} else {
throw new Error(`响应状态: ${response.status}`);
} }
} catch (error) { } catch (error) {
console.error('获取评查点数据失败:', error); console.error('获取评查点数据失败:', error);
alert(`获取评查点数据失败: ${error instanceof Error ? error.message : '未知错误'}`); alert(`获取评查点数据失败: ${error instanceof Error ? error.message : '未知错误'}`);
// 获取数据失败时返回上一页 // 获取数据失败时返回上一页
navigate(-1); resetFormData();
navigate('/rules');
} finally { } finally {
setIsLoading(false); setIsLoading(false);
} }
}, [navigate, extractFieldsFromFormData]); }, [navigate, extractFieldsFromFormData, resetFormData]);
/** /**
* 获取评查点组数据 * 获取评查点组数据
@@ -604,15 +667,20 @@ export default function RuleNew() {
const id = searchParams.get('id'); const id = searchParams.get('id');
// 设置编辑模式 // 设置编辑模式
setIsEditMode(!!id); const newIsEditMode = !!id;
setIsEditMode(newIsEditMode);
if (id) { if (id) {
// 编辑模式:获取数据
fetchEvaluationPoint(parseInt(id)); fetchEvaluationPoint(parseInt(id));
} else {
// 新建模式:重置表单数据
resetFormData();
} }
// 获取评查点组数据 // 获取评查点组数据
fetchEvaluationPointGroups(); fetchEvaluationPointGroups();
}, [location.search, fetchEvaluationPoint, fetchEvaluationPointGroups]); }, [location.search, fetchEvaluationPoint, fetchEvaluationPointGroups, resetFormData]);
// 渲染页面内容 // 渲染页面内容
return ( return (
@@ -634,61 +702,63 @@ export default function RuleNew() {
extractionFields, extractionFields,
updateFields: setExtractionFields updateFields: setExtractionFields
}}> }}>
{/* 评查点基本信息设置 */} {/* 使用key属性强制在模式切换时重新渲染所有组件 */}
<div className="mb-8"> <div key={instanceKey}>
<BasicInfo {/* 评查点基本信息设置 */}
onChange={handleBasicInfoChange} <div className="mb-8">
initialData={formData} <BasicInfo
evaluationPointGroups={evaluationPointGroups} onChange={handleBasicInfoChange}
riskOptions={EVALUATION_OPTIONS.riskLevelOptions} initialData={formData}
evaluationPointGroups={evaluationPointGroups}
riskOptions={EVALUATION_OPTIONS.riskLevelOptions}
/>
</div>
{/* 抽取设置 - 配置从文档中提取的字段 */}
<div className="mb-8">
<ExtractionSettings
onChange={handleExtractionSettingsChange}
initialData={formData}
promptTypeOptions={EVALUATION_OPTIONS.promptTypeOptions}
vlmFieldTypeOptions={EVALUATION_OPTIONS.vlmFieldTypeOptions}
/>
</div>
{/* 评查设置 - 配置评查规则、消息等 */}
<div className="mb-8">
<ReviewSettings
onChange={handleReviewSettingsChange}
initialData={{
rules: formData.evaluation_config?.rules || [],
combinationLogic: formData.evaluation_config?.logicType || 'and',
customLogic: formData.evaluation_config?.customLogic || '',
pass_message: formData.pass_message || '文档检查通过,符合规范要求。',
fail_message: formData.fail_message || '文档存在以下问题,请修改后重新提交。',
suggestion_message: formData.suggestion_message || '',
suggestion_message_type: formData.suggestion_message_type || 'warning',
post_action: formData.post_action || 'none',
action_config: formData.action_config || '',
score: formData.score !== undefined ? formData.score : 0
}}
ruleTypeOptions={EVALUATION_OPTIONS.ruleTypeOptions}
logicTypeOptions={EVALUATION_OPTIONS.logicTypeOptions}
logicOperatorOptions={EVALUATION_OPTIONS.logicOperatorOptions}
compareMethodOptions={EVALUATION_OPTIONS.compareMethodOptions}
formatTypeOptions={EVALUATION_OPTIONS.formatTypeOptions}
comparisonOperatorOptions={EVALUATION_OPTIONS.comparisonOperatorOptions}
matchTypeOptions={EVALUATION_OPTIONS.matchTypeOptions}
suggestionMessageTypeOptions={EVALUATION_OPTIONS.suggestionMessageTypeOptions}
postActionOptions={EVALUATION_OPTIONS.postActionOptions}
/>
</div>
{/* 底部操作按钮区域 */}
<ActionButtons
onSave={handleSave}
onSaveDraft={handleSaveDraft}
isEditMode={isEditMode}
/> />
</div> </div>
{/* 抽取设置 - 配置从文档中提取的字段 */}
<div className="mb-8">
<ExtractionSettings
onChange={handleExtractionSettingsChange}
initialData={formData}
promptTypeOptions={EVALUATION_OPTIONS.promptTypeOptions}
vlmFieldTypeOptions={EVALUATION_OPTIONS.vlmFieldTypeOptions}
/>
</div>
{/* 评查设置 - 配置评查规则、消息等 */}
<div className="mb-8">
<ReviewSettings
key={`review-settings-${extractionFields.length}-${isEditMode ? formData.id : 'new'}`}
onChange={handleReviewSettingsChange}
initialData={{
rules: formData.evaluation_config?.rules || [],
combinationLogic: formData.evaluation_config?.logicType || 'and',
customLogic: formData.evaluation_config?.customLogic || '',
pass_message: formData.pass_message || '',
fail_message: formData.fail_message || '',
suggestion_message: formData.suggestion_message || '',
suggestion_message_type: formData.suggestion_message_type || 'warning',
post_action: formData.post_action || 'none',
action_config: formData.action_config || '',
score: formData.score || 0
}}
ruleTypeOptions={EVALUATION_OPTIONS.ruleTypeOptions}
logicTypeOptions={EVALUATION_OPTIONS.logicTypeOptions}
logicOperatorOptions={EVALUATION_OPTIONS.logicOperatorOptions}
compareMethodOptions={EVALUATION_OPTIONS.compareMethodOptions}
formatTypeOptions={EVALUATION_OPTIONS.formatTypeOptions}
comparisonOperatorOptions={EVALUATION_OPTIONS.comparisonOperatorOptions}
matchTypeOptions={EVALUATION_OPTIONS.matchTypeOptions}
suggestionMessageTypeOptions={EVALUATION_OPTIONS.suggestionMessageTypeOptions}
postActionOptions={EVALUATION_OPTIONS.postActionOptions}
/>
</div>
{/* 底部操作按钮区域 */}
<ActionButtons
onSave={handleSave}
onSaveDraft={handleSaveDraft}
isEditMode={isEditMode}
/>
</RuleContext.Provider> </RuleContext.Provider>
)} )}
</div> </div>