修复好前段逻辑,
This commit is contained in:
@@ -50,23 +50,6 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
|
||||
llm: ''
|
||||
});
|
||||
|
||||
// 获取所有可用字段(合并大模型、多模态和正则抽取的字段)
|
||||
const getAllFields = (): string[] => {
|
||||
const llm_ocr_fields = fields.llm_ocr || [];
|
||||
// 从多模态字段中提取基本字段名(去除类型后缀)
|
||||
const llm_fields = (fields.llm || []).map(field => {
|
||||
const [fieldName] = field.split('_');
|
||||
return fieldName;
|
||||
});
|
||||
// 获取正则字段名
|
||||
const regex_fields = regexFields
|
||||
.map(field => field.fieldName)
|
||||
.filter(name => name.trim() !== '');
|
||||
|
||||
// 合并并去重
|
||||
return [...new Set([...llm_ocr_fields, ...llm_fields, ...regex_fields])];
|
||||
};
|
||||
|
||||
// 在组件初始化时,如果Context中已有字段数据,则使用Context数据初始化
|
||||
useEffect(() => {
|
||||
if (ruleContext && ruleContext.extractionFields.length > 0) {
|
||||
@@ -78,6 +61,79 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
|
||||
}
|
||||
}, []);
|
||||
|
||||
// 当组件首次加载时更新字段
|
||||
useEffect(() => {
|
||||
updateAllFields();
|
||||
}, []);
|
||||
|
||||
// 获取所有可用字段(合并大模型、多模态和正则抽取的字段)
|
||||
const getAllFields = (): string[] => {
|
||||
// 从大模型OCR抽取中获取字段
|
||||
const llm_ocr_fields = fields.llm_ocr || [];
|
||||
|
||||
// 从多模态字段中提取基本字段名(去除类型后缀)
|
||||
const llm_fields = (fields.llm || []).map(field => {
|
||||
const [fieldName] = field.split('_');
|
||||
return fieldName;
|
||||
});
|
||||
|
||||
// 获取正则字段名
|
||||
const regex_fields = regexFields
|
||||
.map(field => field.fieldName)
|
||||
.filter(name => name.trim() !== '');
|
||||
|
||||
// 合并并去重
|
||||
const allFields = [...new Set([...llm_ocr_fields, ...llm_fields, ...regex_fields])];
|
||||
console.log("所有可用字段:", allFields);
|
||||
return allFields;
|
||||
};
|
||||
|
||||
// 检查字段名是否存在(精确匹配)
|
||||
const isFieldNameExists = (fieldName: string, excludeId?: string): boolean => {
|
||||
// 获取所有字段名称(不转换为小写)
|
||||
const existingFields = getAllFields();
|
||||
|
||||
// 检查精确匹配(区分大小写)
|
||||
for (const existingField of existingFields) {
|
||||
// 严格相等比较,确保完全匹配而不是部分匹配
|
||||
if (existingField === fieldName) {
|
||||
console.log(`字段名 '${fieldName}' 在现有字段中存在(严格匹配)`);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查正则字段组中的其他字段(精确匹配)
|
||||
// 排除当前正在编辑的字段ID
|
||||
const otherRegexFields = regexFields
|
||||
.filter(f => !excludeId || f.id !== excludeId)
|
||||
.map(f => f.fieldName);
|
||||
|
||||
for (const regexField of otherRegexFields) {
|
||||
// 严格相等比较
|
||||
if (regexField === fieldName) {
|
||||
console.log(`字段名 '${fieldName}' 在正则字段中存在(严格匹配)`);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 不区分大小写的检查(保留这部分功能,但仍然是精确匹配)
|
||||
const fieldNameLower = fieldName.toLowerCase();
|
||||
const existingFieldsLower = existingFields.map(f => f.toLowerCase());
|
||||
const otherRegexFieldsLower = otherRegexFields.map(f => f.toLowerCase());
|
||||
|
||||
if (existingFieldsLower.includes(fieldNameLower)) {
|
||||
console.log(`字段名 '${fieldName}' 在现有字段中存在(不区分大小写)`);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (otherRegexFieldsLower.includes(fieldNameLower)) {
|
||||
console.log(`字段名 '${fieldName}' 在正则字段中存在(不区分大小写)`);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// 更新所有抽取字段到Context
|
||||
const updateAllFields = () => {
|
||||
const allFields = getAllFields();
|
||||
@@ -111,10 +167,13 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
|
||||
}
|
||||
};
|
||||
|
||||
// 在所有字段集合变化时自动更新
|
||||
// 使用useEffect监听字段变化并更新Context
|
||||
useEffect(() => {
|
||||
// 立即更新字段列表
|
||||
updateAllFields();
|
||||
}, [fields, regexFields]);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [fields.llm_ocr, fields.llm, regexFields]);
|
||||
|
||||
const handleTabChange = (tab: string) => {
|
||||
setCurrentTab(tab);
|
||||
@@ -141,19 +200,40 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
|
||||
|
||||
// OCR+LLM模式下,支持多个字段同时添加(用逗号、顿号或空格分隔)
|
||||
if (type === 'llm_ocr') {
|
||||
newFields = [
|
||||
...fields[type],
|
||||
...inputValue[type].split(/[\s、,]+/).map(f => f.trim()).filter(f => f !== '')
|
||||
];
|
||||
const fieldsToAdd = inputValue[type].split(/[\s、,]+/)
|
||||
.map(f => f.trim())
|
||||
.filter(f => f !== '');
|
||||
|
||||
console.log(`添加OCR字段:`, fieldsToAdd);
|
||||
|
||||
// 仅添加不存在的字段
|
||||
const uniqueFields = fieldsToAdd.filter(field => !isFieldNameExists(field));
|
||||
|
||||
if (uniqueFields.length === 0) {
|
||||
// 如果没有唯一字段可添加,显示提示并返回
|
||||
alert("所有字段名已存在,请确保字段名称唯一");
|
||||
return;
|
||||
}
|
||||
|
||||
newFields = [...fields[type], ...uniqueFields];
|
||||
} else {
|
||||
// 多模态抽取模式下,一次只添加一个字段(带类型)
|
||||
newFields = [...fields[type], `${inputValue[type].trim()}_${selectedFieldType}`];
|
||||
// 多模态抽取模式下,处理字段名称唯一性
|
||||
const fieldName = inputValue[type].trim();
|
||||
console.log(`添加多模态字段:${fieldName}`);
|
||||
|
||||
// 检查字段名是否已存在
|
||||
if (isFieldNameExists(fieldName)) {
|
||||
alert(`字段名 "${fieldName}" 已存在,请确保字段名称唯一`);
|
||||
return;
|
||||
}
|
||||
|
||||
newFields = [...fields[type], `${fieldName}_${selectedFieldType}`];
|
||||
}
|
||||
|
||||
setFields({
|
||||
...fields,
|
||||
setFields(prevFields => ({
|
||||
...prevFields,
|
||||
[type]: newFields
|
||||
});
|
||||
}));
|
||||
|
||||
setInputValue({
|
||||
...inputValue,
|
||||
@@ -163,9 +243,6 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
|
||||
if (type === 'llm') {
|
||||
setSelectedFieldType('default');
|
||||
}
|
||||
|
||||
// 立即触发字段更新事件,通知评查设置组件
|
||||
setTimeout(() => updateAllFields(), 0);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -180,13 +257,18 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
|
||||
const newFields = [...fields[type]];
|
||||
newFields.splice(index, 1);
|
||||
|
||||
setFields({
|
||||
...fields,
|
||||
[type]: newFields
|
||||
// 使用新的方式更新,确保状态立即更新并触发后续操作
|
||||
setFields(prevFields => {
|
||||
const updatedFields = {
|
||||
...prevFields,
|
||||
[type]: newFields
|
||||
};
|
||||
|
||||
// 状态更新后立即触发字段更新事件
|
||||
Promise.resolve().then(() => updateAllFields());
|
||||
|
||||
return updatedFields;
|
||||
});
|
||||
|
||||
// 立即触发字段更新事件,通知评查设置组件
|
||||
setTimeout(() => updateAllFields(), 0);
|
||||
};
|
||||
|
||||
// 添加正则表达式字段行
|
||||
@@ -223,19 +305,20 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
|
||||
}
|
||||
};
|
||||
|
||||
// 更新正则表达式字段值
|
||||
// 更新正则表达式字段
|
||||
const updateRegexField = (id: string, key: 'fieldName' | 'regex', value: string) => {
|
||||
const newRegexFields = regexFields.map(field =>
|
||||
field.id === id ? { ...field, [key]: value } : field
|
||||
);
|
||||
// 更新字段值
|
||||
const newRegexFields = regexFields.map(field => {
|
||||
if (field.id === id) {
|
||||
return { ...field, [key]: value };
|
||||
}
|
||||
return field;
|
||||
});
|
||||
|
||||
// 仅更新状态,不触发其他事件
|
||||
setRegexFields(newRegexFields);
|
||||
|
||||
// 如果更新的是字段名,则触发字段更新事件
|
||||
if (key === 'fieldName') {
|
||||
setTimeout(() => updateAllFields(), 0);
|
||||
}
|
||||
|
||||
// 更新onChange回调
|
||||
if (onChange) {
|
||||
onChange({
|
||||
extractionMethod: currentTab,
|
||||
@@ -244,6 +327,74 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
|
||||
}
|
||||
};
|
||||
|
||||
// 处理正则字段失去焦点事件,检查唯一性并更新字段列表
|
||||
const handleRegexFieldBlur = (id: string, key: 'fieldName' | 'regex') => {
|
||||
// 只有在修改字段名时需要检查唯一性并更新字段列表
|
||||
if (key === 'fieldName') {
|
||||
const currentField = regexFields.find(field => field.id === id);
|
||||
if (currentField && currentField.fieldName.trim() !== '') {
|
||||
const fieldName = currentField.fieldName.trim();
|
||||
console.log(`检查正则字段 '${fieldName}' 的唯一性,ID: ${id}`);
|
||||
|
||||
// 检查当前正则字段组中是否有重名(排除自身)
|
||||
const duplicateInRegex = regexFields
|
||||
.filter(f => f.id !== id)
|
||||
.find(f => f.fieldName === fieldName);
|
||||
|
||||
if (duplicateInRegex) {
|
||||
console.log(`字段名 '${fieldName}' 在正则字段中存在重复,ID: ${duplicateInRegex.id}`);
|
||||
alert(`字段名 "${fieldName}" 已存在,请确保字段名称唯一`);
|
||||
|
||||
// 重置为空字段名
|
||||
const resetFields = regexFields.map(field => {
|
||||
if (field.id === id) {
|
||||
return { ...field, fieldName: '' };
|
||||
}
|
||||
return field;
|
||||
});
|
||||
|
||||
setRegexFields(resetFields);
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查其他抽取方法中的字段(不区分大小写)
|
||||
const otherExtractFields = [
|
||||
...fields.llm_ocr.map(f => f.toLowerCase()),
|
||||
...fields.llm.map(f => {
|
||||
const [name] = f.split('_');
|
||||
return name.toLowerCase();
|
||||
})
|
||||
];
|
||||
|
||||
const fieldNameLower = fieldName.toLowerCase();
|
||||
const duplicateInOtherMethods = otherExtractFields.includes(fieldNameLower);
|
||||
|
||||
if (duplicateInOtherMethods) {
|
||||
console.log(`字段名 '${fieldName}' 在其他抽取方法中存在(不区分大小写)`);
|
||||
alert(`字段名 "${fieldName}" 已存在,请确保字段名称唯一`);
|
||||
|
||||
// 重置为空字段名
|
||||
const resetFields = regexFields.map(field => {
|
||||
if (field.id === id) {
|
||||
return { ...field, fieldName: '' };
|
||||
}
|
||||
return field;
|
||||
});
|
||||
|
||||
setRegexFields(resetFields);
|
||||
return;
|
||||
}
|
||||
|
||||
// 字段名有效,更新字段列表
|
||||
console.log(`字段名 '${fieldName}' 检查通过,更新字段列表`);
|
||||
updateAllFields();
|
||||
}
|
||||
} else {
|
||||
// 对于regex字段,只需更新字段列表
|
||||
updateAllFields();
|
||||
}
|
||||
};
|
||||
|
||||
// 应用正则模板
|
||||
const applyRegexTemplate = (regex: string) => {
|
||||
// 找到当前正在编辑的行,或者最后一行
|
||||
@@ -909,6 +1060,7 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
|
||||
placeholder="如:合同编号"
|
||||
value={field.fieldName}
|
||||
onChange={(e) => updateRegexField(field.id, 'fieldName', e.target.value)}
|
||||
onBlur={() => handleRegexFieldBlur(field.id, 'fieldName')}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-7/10 mr-2">
|
||||
@@ -920,6 +1072,7 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
|
||||
placeholder="如:\\d{4}[-/年](0?[1-9]|1[0-2])[-/月](0?[1-9]|[12][0-9]|3[01])[日]?"
|
||||
value={field.regex}
|
||||
onChange={(e) => updateRegexField(field.id, 'regex', e.target.value)}
|
||||
onBlur={() => handleRegexFieldBlur(field.id, 'regex')}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col justify-end pt-3">
|
||||
|
||||
Reference in New Issue
Block a user