第一版完成

This commit is contained in:
2025-03-28 15:15:05 +08:00
parent 0079786b25
commit aae2bc10b2
3 changed files with 410 additions and 243 deletions
+65 -65
View File
@@ -50,6 +50,23 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
llm: '' 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数据初始化 // 在组件初始化时,如果Context中已有字段数据,则使用Context数据初始化
useEffect(() => { useEffect(() => {
if (ruleContext && ruleContext.extractionFields.length > 0) { if (ruleContext && ruleContext.extractionFields.length > 0) {
@@ -61,14 +78,47 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
} }
}, []); }, []);
// 更新所有抽取字段到Context
const updateAllFields = () => {
const allFields = getAllFields();
// 更新全局Context中的字段
if (ruleContext) {
ruleContext.updateExtractionFields(allFields);
}
// 触发自定义事件,通知字段已更新(兼容非Context的实现)
const event = new CustomEvent('extraction-fields-updated', {
detail: {
fields: allFields,
tab: currentTab,
fieldsData: {
llm_ocr: fields.llm_ocr || [],
llm: fields.llm || [],
regex: regexFields.map(f => f.fieldName).filter(name => name.trim() !== '')
}
}
});
document.dispatchEvent(event);
if (onChange) {
onChange({
extractionMethod: currentTab,
fields,
regexFields,
allFields // 添加合并后的所有字段
});
}
};
// 在所有字段集合变化时自动更新
useEffect(() => {
updateAllFields();
}, [fields, regexFields]);
const handleTabChange = (tab: string) => { const handleTabChange = (tab: string) => {
setCurrentTab(tab); setCurrentTab(tab);
// 当切换抽取方法时,更新全局Context中的字段
if (ruleContext && fields[tab]) {
ruleContext.updateExtractionFields(fields[tab]);
}
if (onChange) { if (onChange) {
onChange({ extractionMethod: tab }); onChange({ extractionMethod: tab });
} }
@@ -114,26 +164,8 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
setSelectedFieldType('default'); setSelectedFieldType('default');
} }
// 更新全局Context中的字段 // 立即触发字段更新事件,通知评查设置组件
if (ruleContext) { setTimeout(() => updateAllFields(), 0);
ruleContext.updateExtractionFields(newFields);
}
if (onChange) {
onChange({
extractionMethod: currentTab,
fields: {
...fields,
[type]: newFields
}
});
}
// 触发自定义事件,通知字段已更新(兼容非Context的实现)
const event = new CustomEvent('extraction-fields-updated', {
detail: { fields: newFields }
});
document.dispatchEvent(event);
} }
}; };
@@ -153,26 +185,8 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
[type]: newFields [type]: newFields
}); });
// 更新全局Context中的字段 // 立即触发字段更新事件,通知评查设置组件
if (ruleContext) { setTimeout(() => updateAllFields(), 0);
ruleContext.updateExtractionFields(newFields);
}
if (onChange) {
onChange({
extractionMethod: currentTab,
fields: {
...fields,
[type]: newFields
}
});
}
// 触发自定义事件,通知字段已更新(兼容非Context的实现)
const event = new CustomEvent('extraction-fields-updated', {
detail: { fields: newFields }
});
document.dispatchEvent(event);
}; };
// 添加正则表达式字段行 // 添加正则表达式字段行
@@ -180,14 +194,15 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
const newId = `${regexFields.length + 1}`; const newId = `${regexFields.length + 1}`;
setRegexFields([...regexFields, { id: newId, fieldName: '', regex: '' }]); setRegexFields([...regexFields, { id: newId, fieldName: '', regex: '' }]);
// 如果是新增了regex字段,也要更新字段列表通知评查设置组件
setTimeout(() => updateAllFields(), 0);
if (onChange) { if (onChange) {
onChange({ onChange({
extractionMethod: currentTab, extractionMethod: currentTab,
regexFields: [...regexFields, { id: newId, fieldName: '', regex: '' }] regexFields: [...regexFields, { id: newId, fieldName: '', regex: '' }]
}); });
} }
// 添加字段时不触发事件,因为此时字段名称尚未填写
}; };
// 删除正则表达式字段行 // 删除正则表达式字段行
@@ -216,13 +231,9 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
setRegexFields(newRegexFields); setRegexFields(newRegexFields);
// 如果是字段名更新且当前抽取方法是正则抽取,则更新Context // 如果更新的是字段名,则触发字段更新事件
if (key === 'fieldName' && currentTab === 'ocr_regex' && ruleContext) { if (key === 'fieldName') {
const fieldNames = newRegexFields setTimeout(() => updateAllFields(), 0);
.map(field => field.fieldName)
.filter(name => name.trim() !== '');
ruleContext.updateExtractionFields(fieldNames);
} }
if (onChange) { if (onChange) {
@@ -231,17 +242,6 @@ export function ExtractionSettings({ onChange }: ExtractionSettingsProps) {
regexFields: newRegexFields regexFields: newRegexFields
}); });
} }
// 如果更新的是字段名,触发自定义事件通知字段已更新
if (key === 'fieldName' && value.trim()) {
const allFieldNames = [...fields[currentTab], ...newRegexFields.map(f => f.fieldName).filter(f => f)];
// 触发自定义事件,通知字段已更新(兼容非Context的实现)
const event = new CustomEvent('extraction-fields-updated', {
detail: { fields: allFieldNames }
});
document.dispatchEvent(event);
}
}; };
// 应用正则模板 // 应用正则模板
+309 -153
View File
@@ -57,60 +57,51 @@ export function ReviewSettings({ onChange }: ReviewSettingsProps) {
// 监听抽取设置中的字段变化 // 监听抽取设置中的字段变化
useEffect(() => { useEffect(() => {
// 当Context中的字段发生变化时,立即更新可用字段 // 当Context中的字段发生变化时,更新可用字段但保留已有配置
if (extractionFields.length > 0) { if (extractionFields.length > 0) {
// 检查是否有字段被删除
const deletedFields = availableFields.filter(field => !extractionFields.includes(field));
// 处理新增的字段
const newFields = extractionFields.filter((field: string) => !availableFields.includes(field));
if (newFields.length > 0 || deletedFields.length > 0) {
// 设置最新的可用字段列表
setAvailableFields(extractionFields); setAvailableFields(extractionFields);
// 同时更新已有规则中的可选字段状态 // 处理规则中已删除的字段
if (deletedFields.length > 0) {
handleDeletedFields(deletedFields);
}
// 使用最新的字段列表更新规则配置
updateRulesWithNewFields(extractionFields); updateRulesWithNewFields(extractionFields);
return; }
} }
// 获取抽取字段函数 - 当Context不可用时的备选方案 // 监听抽取设置的变化 - 用于捕获非Context更新的情况
const getExtractedFields = (): string[] => {
const extractedFields: string[] = [];
// 查找当前活跃的抽取设置容器
const activeExtractConfig = document.querySelector('.extraction-config:not(.hidden)');
if (!activeExtractConfig) {
// 如果没有找到活跃的配置,返回空数组
return [];
}
// 查找字段容器
const fieldsContainer = activeExtractConfig.querySelector('.chips-container');
if (fieldsContainer) {
// 获取所有字段芯片
const chips = fieldsContainer.querySelectorAll('.chip');
chips.forEach(chip => {
const fieldName = chip.textContent?.replace('×', '').trim();
if (fieldName) {
extractedFields.push(fieldName);
}
});
}
// 查找正则字段
const regexFields = document.querySelectorAll('.regex-field-row');
regexFields.forEach(row => {
const fieldNameInput = row.querySelector('input[placeholder="字段名称"]');
if (fieldNameInput instanceof HTMLInputElement && fieldNameInput.value.trim()) {
extractedFields.push(fieldNameInput.value.trim());
}
});
return extractedFields;
};
// 初始化获取字段 - 仅在Context不可用时使用
setAvailableFields(getExtractedFields());
// 监听抽取设置的变化 - 仅在Context不可用时使用
const handleExtractionChange = (event: Event) => { const handleExtractionChange = (event: Event) => {
if (event instanceof CustomEvent && event.detail && Array.isArray(event.detail.fields)) { if (event instanceof CustomEvent && event.detail && Array.isArray(event.detail.fields)) {
setAvailableFields(event.detail.fields); const incomingFields = event.detail.fields;
} else {
setAvailableFields(getExtractedFields()); // 检查是否有字段被删除
const deletedFields = availableFields.filter(field => !incomingFields.includes(field));
// 识别新增的字段
const newFields = incomingFields.filter((field: string) => !availableFields.includes(field));
if (newFields.length > 0 || deletedFields.length > 0) {
// 设置最新的可用字段列表
setAvailableFields(incomingFields);
// 处理规则中已删除的字段
if (deletedFields.length > 0) {
handleDeletedFields(deletedFields);
}
// 使用最新的字段列表更新规则配置
updateRulesWithNewFields(incomingFields);
}
} }
}; };
@@ -121,39 +112,110 @@ export function ReviewSettings({ onChange }: ReviewSettingsProps) {
return () => { return () => {
document.removeEventListener('extraction-fields-updated', handleExtractionChange); document.removeEventListener('extraction-fields-updated', handleExtractionChange);
}; };
}, [extractionFields]); }, [extractionFields, availableFields]);
// 当可用字段发生变化时,更新已有规则的配置 // 处理已删除字段的函数
const updateRulesWithNewFields = (newFields: string[]) => { const handleDeletedFields = (deletedFields: string[]) => {
// 更新已有规则中的字段选择,保留已选择的字段 setRules(prevRules => {
const updatedRules = rules.map(rule => { return prevRules.map(rule => {
if (rule.type === 'exists' || rule.type === 'consistency' || rule.type === 'logic' || rule.type === 'regex') { const updatedConfig = { ...rule.config };
// 检查和更新字段相关的配置
const currentSelectedFields = Array.isArray(rule.config.selectedFields)
? rule.config.selectedFields as string[]
: [];
// 使用已选中的字段和新字段的交集作为更新后的选中字段 switch (rule.type) {
const validSelectedFields = currentSelectedFields.filter(field => case 'exists':
newFields.includes(field) || field.trim() !== '' case 'logic':
case 'regex':
// 从已选字段中移除被删除的字段
if (Array.isArray(updatedConfig.selectedFields)) {
updatedConfig.selectedFields = (updatedConfig.selectedFields as string[]).filter(
field => !deletedFields.includes(field)
); );
}
break;
case 'consistency':
// 从配对字段中移除被删除的字段
if (Array.isArray(updatedConfig.pairs)) {
updatedConfig.pairs = (updatedConfig.pairs as ComparisonPair[]).filter(
pair => !deletedFields.includes(pair.sourceField) && !deletedFields.includes(pair.targetField)
);
}
break;
case 'format':
// 如果判断字段被删除,则清空字段
if (updatedConfig.checkField && deletedFields.includes(updatedConfig.checkField as string)) {
updatedConfig.checkField = '';
}
break;
default:
break;
}
// 更新可用字段列表,移除被删除的字段
if (Array.isArray(updatedConfig.availableFields)) {
updatedConfig.availableFields = (updatedConfig.availableFields as string[]).filter(
field => !deletedFields.includes(field)
);
}
return { return {
...rule, ...rule,
config: { config: updatedConfig
...rule.config,
selectedFields: validSelectedFields
}
}; };
}
return rule;
}); });
});
};
setRules(updatedRules); // 更新规则配置中的可用字段但保留已选择的字段和规则配置
const updateRulesWithNewFields = (newFields: string[]) => {
// 更新每个规则的可用字段列表,但保留现有配置
setRules(prevRules => {
return prevRules.map(rule => {
const updatedConfig = { ...rule.config };
if (onChange) { // 对所有规则类型都更新availableFields字段
onChange({ rules: updatedRules }); updatedConfig.availableFields = newFields;
// 根据规则类型更新其他相关字段
if (rule.type) {
switch (rule.type) {
case 'field_validation':
// 保留已有的字段选择,只添加新字段
if (!updatedConfig.fields) {
updatedConfig.fields = [];
} }
break;
case 'field_comparison':
// 保留已配置的比较项
if (!updatedConfig.pairs) {
updatedConfig.pairs = [];
}
break;
case 'field_regex':
// 保留正则表达式配置
break;
case 'custom_code':
break;
default:
// 对于所有类型规则,确保selectedFields字段存在
if (!updatedConfig.selectedFields) {
updatedConfig.selectedFields = [];
}
break;
}
}
return {
...rule,
config: updatedConfig
};
});
});
}; };
const handleLogicChange = (logic: string) => { const handleLogicChange = (logic: string) => {
@@ -218,46 +280,73 @@ export function ReviewSettings({ onChange }: ReviewSettingsProps) {
}; };
const handleRuleTypeChange = (id: string, type: string) => { const handleRuleTypeChange = (id: string, type: string) => {
const updatedRules = rules.map(rule => // 更新规则类型
rule.id === id ? { ...rule, type, config: {} } : rule
);
setRules(updatedRules);
if (onChange) {
onChange({ rules: updatedRules });
}
};
const handleRuleConfigChange = (id: string, config: Record<string, unknown>) => {
const updatedRules = rules.map(rule =>
rule.id === id ? { ...rule, config: { ...rule.config, ...config } } : rule
);
setRules(updatedRules);
if (onChange) {
onChange({ rules: updatedRules });
}
};
// 处理字段选择
const handleFieldSelection = (id: string, fieldName: string, selected: boolean) => {
const updatedRules = rules.map(rule => { const updatedRules = rules.map(rule => {
if (rule.id === id) { if (rule.id === id) {
// 获取当前已选字段 // 为新类型初始化配置
const selectedFields = Array.isArray(rule.config.selectedFields) let initialConfig: Record<string, unknown> = {};
? rule.config.selectedFields as string[]
: [];
// 添加或删除字段 // 根据类型设置初始配置
const newSelectedFields = selected switch(type) {
? [...selectedFields, fieldName] case 'exists':
: selectedFields.filter(f => f !== fieldName); case 'logic':
case 'regex':
initialConfig = {
selectedFields: [],
availableFields: availableFields // 使用当前最新的可用字段列表
};
break;
case 'consistency':
initialConfig = {
pairs: [],
availableFields: availableFields // 使用当前最新的可用字段列表
};
break;
case 'format':
initialConfig = {
formatType: '',
formatParams: '',
availableFields: availableFields // 使用当前最新的可用字段列表
};
break;
default:
// 确保所有规则类型都包含availableFields
initialConfig = {
availableFields: availableFields
};
break;
}
return { return {
...rule, ...rule,
config: { ...rule.config, selectedFields: newSelectedFields } type,
config: initialConfig
};
}
return rule;
});
setRules(updatedRules);
if (onChange) {
onChange({ rules: updatedRules });
}
};
const handleRuleConfigChange = (id: string, configChanges: Record<string, unknown>) => {
const updatedRules = rules.map(rule => {
if (rule.id === id) {
// 合并现有配置和变更
const updatedConfig = { ...rule.config, ...configChanges };
// 确保availableFields字段存在
if (!updatedConfig.availableFields) {
updatedConfig.availableFields = availableFields;
}
return {
...rule,
config: updatedConfig
}; };
} }
return rule; return rule;
@@ -271,49 +360,50 @@ export function ReviewSettings({ onChange }: ReviewSettingsProps) {
}; };
// 渲染字段标签,确保已选择的字段即使在新的字段列表中不存在也会显示 // 渲染字段标签,确保已选择的字段即使在新的字段列表中不存在也会显示
const renderFieldTags = (ruleId: string, ruleConfig: Record<string, unknown>) => { const renderFieldTags = (ruleId: string, config: Record<string, unknown>) => {
const selectedFields = Array.isArray(ruleConfig.selectedFields) // 获取规则的当前已选字段
? ruleConfig.selectedFields as string[] const selectedFields = Array.isArray(config.selectedFields) ? config.selectedFields as string[] : [];
: [];
// 合并已选择的字段和可用字段,以确保已选择但不再可用字段仍然显示 // 优先使用配置中存储的可用字段,如果没有则使用当前可用字段
const allFieldsToRender = [...new Set([...availableFields, ...selectedFields])]; const fieldsToRender = Array.isArray(config.availableFields) ?
config.availableFields as string[] :
return allFieldsToRender.map((field, index) => { availableFields;
const isSelected = selectedFields.includes(field);
const isAvailable = availableFields.includes(field);
const buttonId = `field-tag-${ruleId}-${index}`;
// 如果字段不再可用但已被选中,用特殊样式显示
const fieldClass = !isAvailable && isSelected ? 'field-tag selected unavailable' :
isSelected ? 'field-tag selected' : 'field-tag';
// 只显示可用的字段或已选择的字段
if (!isAvailable && !isSelected) {
return null;
}
return ( return (
<button <div className="field-tags">
type="button" {fieldsToRender.map((field, index) => (
key={buttonId} <div
id={buttonId} key={`field-${ruleId}-${index}`}
className={fieldClass} className={`field-tag ${selectedFields.includes(field) ? 'selected' : ''}`}
data-field={field} onClick={() => {
onClick={() => handleFieldSelection(ruleId, field, !isSelected)} // 切换选中状态
const newSelectedFields = selectedFields.includes(field)
? selectedFields.filter(f => f !== field)
: [...selectedFields, field];
handleRuleConfigChange(ruleId, {
selectedFields: newSelectedFields
});
}}
onKeyDown={(e) => { onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') { if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault(); const newSelectedFields = selectedFields.includes(field)
handleFieldSelection(ruleId, field, !isSelected); ? selectedFields.filter(f => f !== field)
: [...selectedFields, field];
handleRuleConfigChange(ruleId, {
selectedFields: newSelectedFields
});
} }
}} }}
aria-selected={isSelected} role="button"
role="option" tabIndex={0}
> >
{field} {field}
</button> </div>
))}
</div>
); );
}).filter(Boolean); // 过滤掉null值
}; };
// 获取规则类型的Badge样式 // 获取规则类型的Badge样式
@@ -334,6 +424,17 @@ export function ReviewSettings({ onChange }: ReviewSettingsProps) {
const renderRuleConfig = (rule: RuleType) => { const renderRuleConfig = (rule: RuleType) => {
const { id, type, config } = rule; const { id, type, config } = rule;
// 如果规则中的availableFields不是最新的,则更新它
if (type && config && (!config.availableFields ||
(Array.isArray(config.availableFields) &&
!availableFields.every((field) => (config.availableFields as string[]).includes(field))))) {
// 延迟更新以避免在渲染过程中修改状态
setTimeout(() => {
const updatedConfig = { ...config, availableFields: availableFields };
handleRuleConfigChange(id, updatedConfig);
}, 0);
}
if (!type) { if (!type) {
return ( return (
<div className="rule-placeholder text-center py-6 text-secondary"> <div className="rule-placeholder text-center py-6 text-secondary">
@@ -1167,9 +1268,7 @@ export function ReviewSettings({ onChange }: ReviewSettingsProps) {
{/* 评查结果提示信息 */} {/* 评查结果提示信息 */}
<div className="mb-4"> <div className="mb-4">
<label className="form-label"> <h4 className="form-label"></h4>
</label>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div> <div>
<label className="form-label text-sm" htmlFor="pass-message"></label> <label className="form-label text-sm" htmlFor="pass-message"></label>
@@ -1209,57 +1308,114 @@ export function ReviewSettings({ onChange }: ReviewSettingsProps) {
{/* 不通过提示类别 */} {/* 不通过提示类别 */}
<div className="mb-4"> <div className="mb-4">
<label className="form-label" htmlFor="error-severity"></label> <h4 className="form-label"></h4>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4" id="error-severity"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4" role="radiogroup" aria-label="建议信息类别">
<label className={`flex items-center cursor-pointer border-l-4 border-blue-500 bg-blue-50 p-3 hover:bg-blue-100 rounded-r-md severity-option ${errorSeverity === 'info' ? 'selected-severity' : ''}`}> <div
className={`flex items-center cursor-pointer border-l-4 border-blue-500 ${errorSeverity === 'info'
? 'bg-blue-100 shadow-md ring-2 ring-blue-200'
: 'bg-blue-50 hover:bg-blue-100'} p-3 rounded-r-md transition-all duration-200`}
onClick={() => handleSeverityChange('info')}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
handleSeverityChange('info');
}
}}
role="radio"
aria-checked={errorSeverity === 'info'}
tabIndex={0}
>
<input <input
type="radio" type="radio"
name="errorSeverity" name="errorSeverity"
className="severity-radio" id="severity-info"
className="severity-radio hidden"
value="info" value="info"
checked={errorSeverity === 'info'} checked={errorSeverity === 'info'}
onChange={() => handleSeverityChange('info')} onChange={() => handleSeverityChange('info')}
/> />
<i className="ri-information-line text-blue-500 text-xl mr-3"></i> <i className={`ri-information-line text-blue-500 text-xl mr-3 ${errorSeverity === 'info' ? 'animate-pulse' : ''}`}></i>
<div> <div>
<div className="font-medium"> (Info)</div> <div className="font-medium"> (Info)</div>
<div className="text-sm text-gray-500"></div> <div className="text-sm text-gray-500"></div>
</div> </div>
</label> {errorSeverity === 'info' && (
<div className="ml-auto">
<i className="ri-check-line text-blue-500 text-lg"></i>
</div>
)}
</div>
<label className={`flex items-center cursor-pointer border-l-4 border-yellow-500 bg-yellow-50 p-3 hover:bg-yellow-100 rounded-r-md severity-option ${errorSeverity === 'warning' ? 'selected-severity' : ''}`}> <div
className={`flex items-center cursor-pointer border-l-4 border-yellow-500 ${errorSeverity === 'warning'
? 'bg-yellow-100 shadow-md ring-2 ring-yellow-200'
: 'bg-yellow-50 hover:bg-yellow-100'} p-3 rounded-r-md transition-all duration-200`}
onClick={() => handleSeverityChange('warning')}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
handleSeverityChange('warning');
}
}}
role="radio"
aria-checked={errorSeverity === 'warning'}
tabIndex={0}
>
<input <input
type="radio" type="radio"
name="errorSeverity" name="errorSeverity"
className="severity-radio" id="severity-warning"
className="severity-radio hidden"
value="warning" value="warning"
checked={errorSeverity === 'warning'} checked={errorSeverity === 'warning'}
onChange={() => handleSeverityChange('warning')} onChange={() => handleSeverityChange('warning')}
/> />
<i className="ri-alert-line text-yellow-500 text-xl mr-3"></i> <i className={`ri-alert-line text-yellow-500 text-xl mr-3 ${errorSeverity === 'warning' ? 'animate-pulse' : ''}`}></i>
<div> <div>
<div className="font-medium"> (Warning)</div> <div className="font-medium"> (Warning)</div>
<div className="text-sm text-gray-500"></div> <div className="text-sm text-gray-500"></div>
</div> </div>
</label> {errorSeverity === 'warning' && (
<div className="ml-auto">
<i className="ri-check-line text-yellow-500 text-lg"></i>
</div>
)}
</div>
<label className={`flex items-center cursor-pointer border-l-4 border-red-500 bg-red-50 p-3 hover:bg-red-100 rounded-r-md severity-option ${errorSeverity === 'error' ? 'selected-severity' : ''}`}> <div
className={`flex items-center cursor-pointer border-l-4 border-red-500 ${errorSeverity === 'error'
? 'bg-red-100 shadow-md ring-2 ring-red-200'
: 'bg-red-50 hover:bg-red-100'} p-3 rounded-r-md transition-all duration-200`}
onClick={() => handleSeverityChange('error')}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
handleSeverityChange('error');
}
}}
role="radio"
aria-checked={errorSeverity === 'error'}
tabIndex={0}
>
<input <input
type="radio" type="radio"
name="errorSeverity" name="errorSeverity"
className="severity-radio" id="severity-error"
className="severity-radio hidden"
value="error" value="error"
checked={errorSeverity === 'error'} checked={errorSeverity === 'error'}
onChange={() => handleSeverityChange('error')} onChange={() => handleSeverityChange('error')}
/> />
<i className="ri-error-warning-line text-red-500 text-xl mr-3"></i> <i className={`ri-error-warning-line text-red-500 text-xl mr-3 ${errorSeverity === 'error' ? 'animate-pulse' : ''}`}></i>
<div> <div>
<div className="font-medium"> (Error)</div> <div className="font-medium"> (Error)</div>
<div className="text-sm text-gray-500"></div> <div className="text-sm text-gray-500"></div>
</div> </div>
</label> {errorSeverity === 'error' && (
<div className="ml-auto">
<i className="ri-check-line text-red-500 text-lg"></i>
</div> </div>
<div className="form-tip"></div> )}
</div>
</div>
<div className="form-tip mt-2"></div>
</div> </div>
{/* 评查后动作 */} {/* 评查后动作 */}
+12 -1
View File
@@ -44,8 +44,18 @@ export default function RuleNew() {
}; };
const handleExtractionChange = (data: Record<string, unknown>) => { const handleExtractionChange = (data: Record<string, unknown>) => {
// 当抽取设置更新时,获取最新的字段列表 // 使用合并后的所有字段列表
if (data.allFields && Array.isArray(data.allFields)) {
updateExtractionFields(data.allFields);
return;
}
// 旧版本兼容逻辑
if (data.fields) { if (data.fields) {
// 尝试获取合并的字段列表
if (Array.isArray(data.fields)) {
updateExtractionFields(data.fields);
} else {
const fieldData = data.fields as Record<string, string[]>; const fieldData = data.fields as Record<string, string[]>;
const currentMethod = data.extractionMethod as string; const currentMethod = data.extractionMethod as string;
@@ -53,6 +63,7 @@ export default function RuleNew() {
if (fieldData[currentMethod]) { if (fieldData[currentMethod]) {
updateExtractionFields(fieldData[currentMethod]); updateExtractionFields(fieldData[currentMethod]);
} }
}
} else if (data.regexFields) { } else if (data.regexFields) {
// 处理正则字段情况 // 处理正则字段情况
const regexFields = data.regexFields as { id: string; fieldName: string; regex: string }[]; const regexFields = data.regexFields as { id: string; fieldName: string; regex: string }[];