This commit is contained in:
2025-04-10 02:06:56 +08:00
parent 90317d2b4b
commit f99a1f05d4
4 changed files with 759 additions and 1294 deletions
+201 -43
View File
@@ -40,6 +40,9 @@ import type {
} from "~/models/evaluation_points";
import { EVALUATION_OPTIONS } from "~/models/evaluation_points";
import type { EvaluationPointGroup } from "~/models/evaluation_point_groups";
// 导入RuleContext上下文
import { RuleContext } from "~/contexts/RuleContext";
export const meta: MetaFunction = () => {
return [
{ title: "评查点管理 - 中国烟草AI合同及卷宗审核系统" },
@@ -67,6 +70,41 @@ export default function RuleNew() {
const [formData, setFormData] = useState<EvaluationPoint>({});
const [evaluationPointGroups, setEvaluationPointGroups] = useState<EvaluationPointGroup[]>([]);
// 添加用于共享的字段数据状态
const [extractionFields, setExtractionFields] = useState<string[]>([]);
/**
* 从表单数据中提取所有字段
* 用于编辑模式下初始化字段数据
*/
const extractFieldsFromFormData = useCallback((data: EvaluationPoint) => {
if (!data || !data.extraction_config) return [];
const fields: string[] = [];
const config = data.extraction_config;
// 提取LLM字段
if (config.llm && Array.isArray(config.llm.fields)) {
fields.push(...config.llm.fields);
}
// 提取VLM字段
if (config.vlm && Array.isArray(config.vlm.fields)) {
const vlmFields = config.vlm.fields.map((f: string | { name: string, type: string }) =>
typeof f === 'string' ? f : f.name
);
fields.push(...vlmFields);
}
// 提取正则字段
if (config.regex && Array.isArray(config.regex.fields)) {
const regexFields = config.regex.fields.map((f: { field: string, pattern: string }) => f.field).filter(Boolean);
fields.push(...regexFields);
}
return fields;
}, []);
/**
* 获取评查点数据
@@ -88,6 +126,12 @@ export default function RuleNew() {
if (response.ok) {
const data = await response.json();
setFormData(data.data[0]);
// 初始化extractionFields
if (data.data[0]) {
const extractedFields = extractFieldsFromFormData(data.data[0]);
setExtractionFields(extractedFields);
}
}
} catch (error) {
console.error('获取评查点数据失败:', error);
@@ -97,7 +141,7 @@ export default function RuleNew() {
} finally {
setIsLoading(false);
}
}, [navigate]);
}, [navigate, extractFieldsFromFormData]);
/**
* 获取评查点组数据
@@ -127,6 +171,84 @@ export default function RuleNew() {
const handleSave = () => {
console.log("保存评查点", formData);
// 验证必填字段
if (!formData.name?.trim()) {
alert("评查点名称不能为空");
return;
}
if (!formData.code?.trim()) {
alert("评查点编码不能为空");
return;
}
// 显示保存中状态
setIsLoading(true);
// 根据模式决定是创建还是更新
const apiMethod = isEditMode ? 'PATCH' : 'POST';
const apiUrl = isEditMode
? `http://127.0.0.1:9000/admin/evaluation_points?id=eq.${formData.id}`
: 'http://127.0.0.1:9000/admin/evaluation_points';
// 创建一个符合数据库模式的数据副本
const cleanedData = {
id: formData.id,
name: formData.name,
code: formData.code,
risk: formData.risk,
is_enabled: formData.is_enabled !== undefined ? formData.is_enabled : true,
description: formData.description || '',
references_laws: formData.references_laws,
evaluation_point_groups_pid: formData.evaluation_point_groups_pid,
evaluation_point_groups_id: formData.evaluation_point_groups_id,
extraction_config: formData.extraction_config,
evaluation_config: formData.evaluation_config,
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
};
// 如果是新建模式,则删除id字段
if (!isEditMode) {
delete cleanedData.id;
}
console.log("准备提交到API的数据:", cleanedData);
// 发送数据到API
fetch(apiUrl, {
method: apiMethod,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(cleanedData)
})
.then(response => {
if (!response.ok) {
throw new Error(`API错误: ${response.status}`);
}
return response.json();
})
.then(data => {
console.log("保存成功:", data);
alert(`评查点${isEditMode ? '更新' : '创建'}成功!`);
// 保存成功后返回列表页
navigate('/rules');
})
.catch(error => {
console.error("保存失败:", error);
alert(`保存失败: ${error.message}`);
})
.finally(() => {
setIsLoading(false);
});
}
const handleSaveDraft = () => {
@@ -139,12 +261,63 @@ export default function RuleNew() {
const handleExtractionSettingsChange = (data: Record<string, unknown>) => {
setFormData(prev => ({ ...prev, ...data }));
}
// 提取并处理字段数据
const processFields = () => {
// 使用类型断言处理字段访问
const extractionConfig = data.extraction_config as {
llm?: { fields?: string[] };
vlm?: { fields?: Array<string | { name: string, type: string }> };
regex?: { fields?: Array<{ field: string, pattern: string }> };
} | undefined;
if (!extractionConfig) return;
const llmFields = extractionConfig.llm?.fields || [];
const vlmFields = extractionConfig.vlm?.fields || [];
const regexFields = (extractionConfig.regex?.fields || []).map((f: { field: string }) => f.field);
// 合并所有字段
const allFields = [
...llmFields,
...vlmFields.map((f: string | { name: string }) => typeof f === 'string' ? f : f.name),
...regexFields
].filter(Boolean);
setExtractionFields(allFields);
};
// 处理字段数据
if (data.extraction_config) {
processFields();
}
};
const handleReviewSettingsChange = (data: Record<string, unknown>) => {
setFormData(prev => ({ ...prev, ...data }));
}
/**
* 添加事件监听,处理抽取字段更新
*/
useEffect(() => {
// 定义事件处理函数
const handleExtractionFieldsUpdated = (event: CustomEvent<{fields: string[]}>) => {
const { fields } = event.detail;
if (Array.isArray(fields) && fields.length > 0) {
// 更新字段数据
setExtractionFields(fields);
}
};
// 添加事件监听
window.addEventListener('extraction-fields-updated', handleExtractionFieldsUpdated as EventListener);
// 清理函数
return () => {
window.removeEventListener('extraction-fields-updated', handleExtractionFieldsUpdated as EventListener);
};
}, []);
/**
* 页面加载时初始化处理
* 1. 检查URL参数,判断是新建还是编辑模式
@@ -182,7 +355,10 @@ export default function RuleNew() {
<span className="ml-3">...</span>
</div>
) : (
<>
<RuleContext.Provider value={{
extractionFields,
updateFields: setExtractionFields
}}>
{/* 评查点基本信息设置 */}
<div className="mb-8">
<BasicInfo
@@ -197,25 +373,7 @@ export default function RuleNew() {
<div className="mb-8">
<ExtractionSettings
onChange={handleExtractionSettingsChange}
initialData={{
llm: {
fields: formData.extraction_config?.llm?.fields,
prompt_setting: {
type: formData.extraction_config?.llm?.prompt_setting?.type,
template: formData.extraction_config?.llm?.prompt_setting?.template
}
},
vlm: {
fields: formData.extraction_config?.vlm?.fields,
prompt_setting: {
type: formData.extraction_config?.vlm?.prompt_setting?.type,
template: formData.extraction_config?.vlm?.prompt_setting?.template
}
},
regex: {
fields: formData.extraction_config?.regex?.fields
}
}}
initialData={formData}
promptTypeOptions={EVALUATION_OPTIONS.promptTypeOptions}
vlmFieldTypeOptions={EVALUATION_OPTIONS.vlmFieldTypeOptions}
/>
@@ -224,28 +382,28 @@ export default function RuleNew() {
{/* 评查设置 - 配置评查规则、消息等 */}
<div className="mb-8">
<ReviewSettings
key={`review-settings-${isEditMode ? formData.id : 'new'}`}
key={`review-settings-${extractionFields.length}-${isEditMode ? formData.id : 'new'}`}
onChange={handleReviewSettingsChange}
initialData={{
rules: formData.evaluation_config?.rules,
combinationLogic: formData.evaluation_config?.logicType,
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,
post_action: formData.post_action,
action_config: formData.action_config,
score: formData.score
}}
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}
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>
@@ -256,7 +414,7 @@ export default function RuleNew() {
onSaveDraft={handleSaveDraft}
isEditMode={isEditMode}
/>
</>
</RuleContext.Provider>
)}
</div>
);