暂存
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,7 @@
|
||||
import React, { useState, useEffect, useContext, useCallback, useRef } from 'react';
|
||||
import { SimpleCodeEditor } from './SimpleCodeEditor';
|
||||
import { RuleContext } from '~/contexts/RuleContext';
|
||||
import { processFieldNames, areArraysDifferent, getArrayDifference, debounce } from '~/utils';
|
||||
import type {
|
||||
Rule as ModelRule,
|
||||
RuleType as ModelRuleType,
|
||||
LogicType,
|
||||
SuggestionMessageType,
|
||||
PostActionType
|
||||
} from '~/models/evaluation_points';
|
||||
import { processFieldNames, areArraysDifferent, getArrayDifference } from '~/utils';
|
||||
|
||||
interface RuleType {
|
||||
id: string;
|
||||
@@ -60,15 +53,6 @@ interface ReviewSettingsProps {
|
||||
export function ReviewSettings({
|
||||
onChange,
|
||||
initialData,
|
||||
ruleTypeOptions = [],
|
||||
logicTypeOptions = [],
|
||||
logicOperatorOptions = [],
|
||||
compareMethodOptions = [],
|
||||
formatTypeOptions = [],
|
||||
comparisonOperatorOptions = [],
|
||||
matchTypeOptions = [],
|
||||
suggestionMessageTypeOptions = [],
|
||||
postActionOptions = []
|
||||
}: ReviewSettingsProps) {
|
||||
const [rules, setRules] = useState<RuleType[]>([
|
||||
{ id: '1', type: '', config: {} }
|
||||
@@ -227,7 +211,7 @@ export function ReviewSettings({
|
||||
// 只在字段列表实际发生变化时更新
|
||||
if (areArraysDifferent(uniqueFields, availableFields)) {
|
||||
// 检查删除和新增的字段
|
||||
const { added, removed } = getArrayDifference(uniqueFields, availableFields);
|
||||
const { removed } = getArrayDifference(uniqueFields, availableFields);
|
||||
|
||||
// 处理删除的字段
|
||||
if (removed.length > 0) {
|
||||
@@ -467,67 +451,73 @@ export function ReviewSettings({
|
||||
const handleRuleTypeChange = (id: string, type: string) => {
|
||||
const newRules = rules.map(rule => {
|
||||
if (rule.id === id) {
|
||||
// 查找原始规则以获取现有配置
|
||||
const originalRule = rules.find(r => r.id === id);
|
||||
const originalConfig = originalRule ? originalRule.config : {};
|
||||
|
||||
// 为新类型初始化配置
|
||||
let initialConfig: Record<string, unknown> = {};
|
||||
|
||||
// 如果类型没变,保留原配置
|
||||
if (type === rule.type) {
|
||||
initialConfig = { ...rule.config };
|
||||
initialConfig = { ...originalConfig };
|
||||
} else {
|
||||
// 根据类型设置初始配置
|
||||
switch(type) {
|
||||
case 'exists':
|
||||
initialConfig = {
|
||||
fields: [], // 使用fields替代selectedFields
|
||||
logic: 'and', // 使用logic替代existsLogic
|
||||
fields: Array.isArray(originalConfig.fields) ? originalConfig.fields : [],
|
||||
logic: originalConfig.logic || originalConfig.logicRelation || 'and',
|
||||
availableFields: availableFields
|
||||
};
|
||||
break;
|
||||
case 'consistency':
|
||||
initialConfig = {
|
||||
pairs: [],
|
||||
logic: 'and', // 使用logic替代logicRelation
|
||||
pairs: Array.isArray(originalConfig.pairs) ? originalConfig.pairs : [],
|
||||
logic: originalConfig.logic || originalConfig.logicRelation || 'and',
|
||||
availableFields: availableFields
|
||||
};
|
||||
break;
|
||||
case 'format':
|
||||
initialConfig = {
|
||||
field: '', // 用于内部运算
|
||||
checkField: '', // 用于UI展示
|
||||
formatType: '',
|
||||
formatParams: '',
|
||||
field: originalConfig.field || '',
|
||||
checkField: originalConfig.checkField || originalConfig.field || '',
|
||||
formatType: originalConfig.formatType || '',
|
||||
formatParams: originalConfig.formatParams || originalConfig.parameters || '',
|
||||
availableFields: availableFields
|
||||
};
|
||||
break;
|
||||
case 'logic':
|
||||
initialConfig = {
|
||||
conditions: [],
|
||||
logic: 'and', // 使用logic替代logicRelation
|
||||
conditions: Array.isArray(originalConfig.conditions) ? originalConfig.conditions : [],
|
||||
logic: originalConfig.logic || originalConfig.logicRelation || 'and',
|
||||
availableFields: availableFields
|
||||
};
|
||||
break;
|
||||
case 'regex':
|
||||
initialConfig = {
|
||||
field: '', // 用于内部运算
|
||||
checkField: '', // 用于UI展示
|
||||
pattern: '',
|
||||
regexPattern: '', // 用于UI展示
|
||||
matchType: 'match', // 默认为必须匹配
|
||||
field: originalConfig.field || '',
|
||||
checkField: originalConfig.checkField || originalConfig.field || '',
|
||||
pattern: originalConfig.pattern || '',
|
||||
regexPattern: originalConfig.regexPattern || originalConfig.pattern || '',
|
||||
matchType: originalConfig.matchType || 'match',
|
||||
availableFields: availableFields
|
||||
};
|
||||
break;
|
||||
case 'ai':
|
||||
initialConfig = {
|
||||
model: 'qwen14b',
|
||||
temperature: 0.1,
|
||||
prompt: '',
|
||||
model: originalConfig.model || 'qwen14b',
|
||||
temperature: typeof originalConfig.temperature === 'number' ? originalConfig.temperature : 0.1,
|
||||
prompt: originalConfig.prompt || `请判断以下{字段}内容是否符合规范要求,仅回答"符合"或"不符合",并简要说明理由。
|
||||
|
||||
{字段内容}`,
|
||||
availableFields: availableFields
|
||||
};
|
||||
break;
|
||||
case 'code':
|
||||
initialConfig = {
|
||||
language: 'javascript',
|
||||
code: '',
|
||||
language: originalConfig.language || 'javascript',
|
||||
code: originalConfig.code || '',
|
||||
availableFields: availableFields
|
||||
};
|
||||
break;
|
||||
@@ -595,7 +585,10 @@ export function ReviewSettings({
|
||||
// 渲染字段标签,确保已选择的字段即使在新的字段列表中不存在也会显示
|
||||
const renderFieldTags = (ruleId: string, config: Record<string, unknown>) => {
|
||||
// 获取规则的当前已选字段
|
||||
const selectedFields = Array.isArray(config.selectedFields) ? config.selectedFields as string[] : [];
|
||||
// 修复:对于exists类型规则,应该使用fields而不是selectedFields
|
||||
const selectedFields = Array.isArray(config.fields) ?
|
||||
config.fields as string[] :
|
||||
(Array.isArray(config.selectedFields) ? config.selectedFields as string[] : []);
|
||||
|
||||
// 优先使用配置中存储的可用字段,如果没有则使用当前可用字段
|
||||
const fieldsToRender = Array.isArray(config.availableFields) ?
|
||||
@@ -960,8 +953,15 @@ export function ReviewSettings({
|
||||
name={`logicRelation_${id}`}
|
||||
className="form-radio"
|
||||
value="and"
|
||||
checked={!config.logicRelation || config.logicRelation === 'and'}
|
||||
onChange={(e) => handleRuleConfigChange(id, { logicRelation: e.target.value })}
|
||||
checked={!config.logic && !config.logicRelation ? true : (config.logic === 'and' || config.logicRelation === 'and')}
|
||||
onChange={(e) => {
|
||||
handleRuleConfigChange(id, {
|
||||
logicRelation: e.target.value,
|
||||
logic: e.target.value
|
||||
});
|
||||
// 触发配置更新
|
||||
generateEvaluationConfig();
|
||||
}}
|
||||
/>
|
||||
<span>AND(所有条件都满足)</span>
|
||||
</label>
|
||||
@@ -971,8 +971,15 @@ export function ReviewSettings({
|
||||
name={`logicRelation_${id}`}
|
||||
className="form-radio"
|
||||
value="or"
|
||||
checked={config.logicRelation === 'or'}
|
||||
onChange={(e) => handleRuleConfigChange(id, { logicRelation: e.target.value })}
|
||||
checked={config.logic === 'or' || config.logicRelation === 'or'}
|
||||
onChange={(e) => {
|
||||
handleRuleConfigChange(id, {
|
||||
logicRelation: e.target.value,
|
||||
logic: e.target.value
|
||||
});
|
||||
// 触发配置更新
|
||||
generateEvaluationConfig();
|
||||
}}
|
||||
/>
|
||||
<span>OR(任一条件满足)</span>
|
||||
</label>
|
||||
@@ -1188,9 +1195,12 @@ export function ReviewSettings({
|
||||
name={`logicRelation_${id}`}
|
||||
className="form-radio"
|
||||
value="and"
|
||||
checked={!config.logicRelation || config.logicRelation === 'and'}
|
||||
checked={!config.logic && !config.logicRelation ? true : (config.logic === 'and' || config.logicRelation === 'and')}
|
||||
onChange={(e) => {
|
||||
handleRuleConfigChange(id, { logicRelation: e.target.value });
|
||||
handleRuleConfigChange(id, {
|
||||
logicRelation: e.target.value,
|
||||
logic: e.target.value
|
||||
});
|
||||
// 触发配置更新
|
||||
generateEvaluationConfig();
|
||||
}}
|
||||
@@ -1203,9 +1213,12 @@ export function ReviewSettings({
|
||||
name={`logicRelation_${id}`}
|
||||
className="form-radio"
|
||||
value="or"
|
||||
checked={config.logicRelation === 'or'}
|
||||
checked={config.logic === 'or' || config.logicRelation === 'or'}
|
||||
onChange={(e) => {
|
||||
handleRuleConfigChange(id, { logicRelation: e.target.value });
|
||||
handleRuleConfigChange(id, {
|
||||
logicRelation: e.target.value,
|
||||
logic: e.target.value
|
||||
});
|
||||
// 触发配置更新
|
||||
generateEvaluationConfig();
|
||||
}}
|
||||
@@ -1302,7 +1315,12 @@ export function ReviewSettings({
|
||||
<select
|
||||
id={`ai-model-${id}`}
|
||||
className="form-select"
|
||||
onChange={(e) => handleRuleConfigChange(id, { model: e.target.value })}
|
||||
value={config.model as string || 'qwen14b'}
|
||||
onChange={(e) => {
|
||||
handleRuleConfigChange(id, { model: e.target.value });
|
||||
// 直接触发配置更新
|
||||
generateEvaluationConfig();
|
||||
}}
|
||||
>
|
||||
<option value="deepseek">DeepSeek</option>
|
||||
<option value="qwen72b">Qwen72B-VL</option>
|
||||
@@ -1316,11 +1334,17 @@ export function ReviewSettings({
|
||||
id={`ai-temp-${id}`}
|
||||
className="form-input"
|
||||
placeholder="0.1"
|
||||
defaultValue="0.1"
|
||||
value={typeof config.temperature === 'number' ? config.temperature : (config.temperature ? parseFloat(String(config.temperature)) : 0.1)}
|
||||
min="0"
|
||||
max="1"
|
||||
step="0.1"
|
||||
onChange={(e) => handleRuleConfigChange(id, { temperature: e.target.value })}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
const numberValue = value === '' ? 0.1 : parseFloat(value);
|
||||
handleRuleConfigChange(id, { temperature: numberValue });
|
||||
// 直接触发配置更新
|
||||
generateEvaluationConfig();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-1 md:col-span-2">
|
||||
@@ -1329,9 +1353,13 @@ export function ReviewSettings({
|
||||
id={`ai-prompt-${id}`}
|
||||
className="form-textarea"
|
||||
placeholder="请输入提示词,引导模型进行判断"
|
||||
defaultValue={`请判断以下{字段}内容是否符合规范要求,仅回答"符合"或"不符合",并简要说明理由。
|
||||
value={
|
||||
typeof config.prompt === 'string' && config.prompt
|
||||
? config.prompt
|
||||
: `请判断以下{字段}内容是否符合规范要求,仅回答"符合"或"不符合",并简要说明理由。
|
||||
|
||||
{字段内容}`}
|
||||
{字段内容}`
|
||||
}
|
||||
onChange={(e) => handleRuleConfigChange(id, { prompt: e.target.value })}
|
||||
></textarea>
|
||||
</div>
|
||||
@@ -1382,8 +1410,11 @@ export function ReviewSettings({
|
||||
name={`codeLanguage_${id}`}
|
||||
className="form-radio"
|
||||
value="javascript"
|
||||
defaultChecked
|
||||
onChange={(e) => handleRuleConfigChange(id, { language: e.target.value })}
|
||||
checked={!config.language || config.language === 'javascript'}
|
||||
onChange={(e) => {
|
||||
handleRuleConfigChange(id, { language: e.target.value });
|
||||
generateEvaluationConfig();
|
||||
}}
|
||||
/>
|
||||
<span>JavaScript</span>
|
||||
</label>
|
||||
@@ -1393,7 +1424,11 @@ export function ReviewSettings({
|
||||
name={`codeLanguage_${id}`}
|
||||
className="form-radio"
|
||||
value="python"
|
||||
onChange={(e) => handleRuleConfigChange(id, { language: e.target.value })}
|
||||
checked={config.language === 'python'}
|
||||
onChange={(e) => {
|
||||
handleRuleConfigChange(id, { language: e.target.value });
|
||||
generateEvaluationConfig();
|
||||
}}
|
||||
/>
|
||||
<span>Python</span>
|
||||
</label>
|
||||
@@ -1402,10 +1437,15 @@ export function ReviewSettings({
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<label className="form-label" htmlFor={`code-editor-${id}`}>自定义代码 <span className="required-mark">*</span></label>
|
||||
<div className="form-tip mb-2">编写返回true或false的评查函数,可以使用字段变量进行判断</div>
|
||||
<SimpleCodeEditor
|
||||
id={`code-editor-${id}`}
|
||||
language={rule.config.language as 'javascript' | 'python' || 'javascript'}
|
||||
onChange={(value) => handleRuleConfigChange(id, { code: value })}
|
||||
initialValue={rule.config.code as string || ''}
|
||||
onChange={(value) => {
|
||||
handleRuleConfigChange(id, { code: value });
|
||||
generateEvaluationConfig();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1490,7 +1530,8 @@ export function ReviewSettings({
|
||||
|
||||
// 生成完整的评查配置数据并在提交保存时使用
|
||||
const generateEvaluationConfig = useCallback(() => {
|
||||
const config = {
|
||||
// 创建符合数据库模式的evaluation_config对象
|
||||
const evaluationConfig = {
|
||||
logicType: combinationLogic,
|
||||
customLogic: combinationLogic === 'custom' ? customLogic : '',
|
||||
rules: rules.map(rule => {
|
||||
@@ -1506,7 +1547,6 @@ export function ReviewSettings({
|
||||
delete processedConfig.selectedFields;
|
||||
}
|
||||
if (processedConfig.existsLogic) {
|
||||
console.log(`[调试] exists规则 ${rule.id} 转换: existsLogic=${processedConfig.existsLogic} 映射到 logic`);
|
||||
processedConfig.logic = processedConfig.existsLogic;
|
||||
delete processedConfig.existsLogic;
|
||||
}
|
||||
@@ -1567,24 +1607,13 @@ export function ReviewSettings({
|
||||
// 使用setTimeout避免连锁更新
|
||||
setTimeout(() => {
|
||||
if (onChange) {
|
||||
onChange({
|
||||
rules: config.rules,
|
||||
combinationLogic: config.logicType,
|
||||
customLogic: config.customLogic,
|
||||
pass_message: pass_message,
|
||||
fail_message: fail_message,
|
||||
suggestion_message: suggestion_message,
|
||||
suggestion_message_type: suggestion_message_type,
|
||||
post_action: post_action,
|
||||
action_config: action_config,
|
||||
score: score,
|
||||
scoreDisplay: scoreDisplay
|
||||
});
|
||||
// 仅将一个evaluation_config对象传递给父组件
|
||||
onChange({ evaluation_config: evaluationConfig });
|
||||
}
|
||||
}, 0);
|
||||
|
||||
return config;
|
||||
}, [rules, combinationLogic, customLogic, pass_message, fail_message, suggestion_message, suggestion_message_type, post_action, action_config, score, scoreDisplay, onChange]);
|
||||
return evaluationConfig;
|
||||
}, [rules, combinationLogic, customLogic, onChange]);
|
||||
|
||||
// 组件初次渲染后,主动发送一次完整配置数据
|
||||
useEffect(() => {
|
||||
@@ -1610,9 +1639,11 @@ export function ReviewSettings({
|
||||
}
|
||||
|
||||
if (onChange) {
|
||||
onChange({ [`${type}_message`]: value });
|
||||
// 触发完整配置生成以确保数据保存
|
||||
generateEvaluationConfig();
|
||||
// 使用正确的字段名
|
||||
const fieldName = type === 'pass' ? 'pass_message' :
|
||||
type === 'fail' ? 'fail_message' :
|
||||
'suggestion_message';
|
||||
onChange({ [fieldName]: value });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1622,8 +1653,6 @@ export function ReviewSettings({
|
||||
|
||||
if (onChange) {
|
||||
onChange({ suggestion_message_type: value });
|
||||
// 触发完整配置生成以确保数据保存
|
||||
generateEvaluationConfig();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1632,26 +1661,21 @@ export function ReviewSettings({
|
||||
// 保存用户输入的显示值
|
||||
setScoreDisplay(value);
|
||||
|
||||
let scoreValue = 0;
|
||||
// 只在值不为空时更新实际分数
|
||||
if (value.trim() !== '') {
|
||||
const numValue = parseFloat(value);
|
||||
if (!isNaN(numValue)) {
|
||||
const validScore = Math.min(Math.max(numValue, 0), 100);
|
||||
setScore(validScore);
|
||||
} else {
|
||||
setScore(0);
|
||||
scoreValue = Math.min(Math.max(numValue, 0), 100);
|
||||
}
|
||||
} else {
|
||||
setScore(0);
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
setScore(scoreValue);
|
||||
|
||||
// 通知父组件
|
||||
if (onChange) {
|
||||
if (value.trim() === '') {
|
||||
// 空值处理
|
||||
onChange({ score: 0, scoreDisplay: '' });
|
||||
} else {
|
||||
onChange({ score: score, scoreDisplay: value });
|
||||
}
|
||||
onChange({ score: scoreValue });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2025,6 +2049,19 @@ export function ReviewSettings({
|
||||
placeholder="请输入分数 (0-100)"
|
||||
value={scoreDisplay}
|
||||
onChange={(e) => handleScoreChange(e.target.value)}
|
||||
onBlur={() => {
|
||||
// 在失去焦点时,如果显示值为空,则设置为0
|
||||
if (scoreDisplay.trim() === '') {
|
||||
setScoreDisplay('0');
|
||||
setScore(0);
|
||||
if (onChange) {
|
||||
onChange({ score: 0 });
|
||||
}
|
||||
} else {
|
||||
// 否则更新为实际分数值的字符串表示
|
||||
setScoreDisplay(String(score));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<span className="ml-2 text-gray-600">分</span>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,7 @@ export function SimpleCodeEditor({
|
||||
language = 'javascript',
|
||||
onChange
|
||||
}: SimpleCodeEditorProps) {
|
||||
const [code, setCode] = useState(initialValue || getDefaultCode(language));
|
||||
const [code, setCode] = useState(initialValue);
|
||||
const [copySuccess, setCopySuccess] = useState(false);
|
||||
|
||||
// 复制代码到剪贴板
|
||||
@@ -33,62 +33,12 @@ export function SimpleCodeEditor({
|
||||
}
|
||||
};
|
||||
|
||||
// 初始示例代码
|
||||
function getDefaultCode(lang: string) {
|
||||
if (lang === 'javascript') {
|
||||
return `// 示例代码
|
||||
function checkRule(data) {
|
||||
// data 包含抽取的字段
|
||||
try {
|
||||
// 在此编写检查逻辑
|
||||
if (data.fieldName && condition) {
|
||||
return {
|
||||
pass: true,
|
||||
message: "检查通过"
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
pass: false,
|
||||
message: "检查不通过,原因:..."
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
pass: false,
|
||||
message: "执行出错:" + error.message
|
||||
};
|
||||
}
|
||||
}`;
|
||||
} else {
|
||||
return `# 示例代码
|
||||
def check_rule(data):
|
||||
# data 包含抽取的字段
|
||||
try:
|
||||
# 在此编写检查逻辑
|
||||
if 'field_name' in data and condition:
|
||||
return {
|
||||
'pass': True,
|
||||
'message': "检查通过"
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'pass': False,
|
||||
'message': "检查不通过,原因:..."
|
||||
}
|
||||
except Exception as error:
|
||||
return {
|
||||
'pass': False,
|
||||
'message': f"执行出错:{str(error)}"
|
||||
}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 当语言变化时更新代码
|
||||
// 更新初始值
|
||||
useEffect(() => {
|
||||
if (!initialValue) {
|
||||
setCode(getDefaultCode(language));
|
||||
if (initialValue !== undefined) {
|
||||
setCode(initialValue);
|
||||
}
|
||||
}, [language, initialValue]);
|
||||
}, [initialValue]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
+201
-43
@@ -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>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user