From a5cad46a844b76d401f0d2b42d891792aac53ba6 Mon Sep 17 00:00:00 2001 From: awen Date: Mon, 7 Apr 2025 20:24:52 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BC=96=E8=BE=91=E6=83=85=E5=86=B5=E4=BC=98?= =?UTF-8?q?=E5=8C=96-=E9=9C=80=E8=A6=81=E7=BB=A7=E7=BB=AD=E5=AE=8C?= =?UTF-8?q?=E5=96=84-=E6=9A=82=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/rules/new/ReviewSettings.tsx | 131 ++++++++++--------- app/routes/rules.new.tsx | 132 +++++++++++++++++--- 2 files changed, 188 insertions(+), 75 deletions(-) diff --git a/app/components/rules/new/ReviewSettings.tsx b/app/components/rules/new/ReviewSettings.tsx index f8603cd..7f8485a 100644 --- a/app/components/rules/new/ReviewSettings.tsx +++ b/app/components/rules/new/ReviewSettings.tsx @@ -73,59 +73,60 @@ export function ReviewSettings({ onChange, initialData }: ReviewSettingsProps) { // 使用useRef跟踪是否已经初始化过 const initializedRef = useRef(false); + // 保存初始数据的引用,用于检测是否有实际变更 + const initialDataRef = useRef(null); // 加载初始数据 useEffect(() => { // 如果已经初始化过,则跳过此次处理 - if (initialData && !initializedRef.current) { - initializedRef.current = true; - console.log('加载初始数据(首次):', initialData); - - // 设置规则 - if (initialData.rules && initialData.rules.length > 0) { - // 确保每个规则都有完整的配置 - const enhancedRules = initialData.rules.map(rule => { - // 根据规则类型,确保config包含必要的字段 - let config = { ...rule.config }; - - // 确保有用于展示的字段 - if (rule.type === 'format' && config.field && !config.checkField) { - config.checkField = config.field; + if (initializedRef.current) { + console.log("ReviewSettings已初始化,跳过后续初始化处理"); + return; + } + + // 记录初始化处理 + console.log("ReviewSettings开始初始化,数据:", initialData); + + // 保存初始数据引用,用于后续比较 + initialDataRef.current = JSON.parse(JSON.stringify(initialData)); + + // 设置已初始化标记 + initializedRef.current = true; + + // 只有在有initialData时才进行初始化设置 + if (initialData) { + // 处理初始规则数据 + if (initialData.rules && Array.isArray(initialData.rules) && initialData.rules.length > 0) { + console.log("设置初始规则数据:", initialData.rules); + + const validRules = initialData.rules.map(rule => { + // 确保每个规则都有id + if (!rule.id) { + rule.id = `rule_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } - if (rule.type === 'regex') { - if (config.field && !config.checkField) { - config.checkField = config.field; - } - if (config.pattern && !config.regexPattern) { - config.regexPattern = config.pattern; - } + // 确保配置对象存在 + if (!rule.config) { + rule.config = {}; } - // 确保存在字段有正确的内部表示 - if (rule.type === 'exists' && config.fields && !config.selectedFields) { - config.selectedFields = config.fields; - config.existsLogic = config.logic || 'all'; + // 添加可用字段 + if (availableFields.length > 0) { + rule.config.availableFields = availableFields; } - // 对于条件逻辑规则 - if ((rule.type === 'consistency' || rule.type === 'logic') && config.logic && !config.logicRelation) { - config.logicRelation = config.logic; - } - - // 确保所有规则都有可用字段列表 - if (!config.availableFields) { - config.availableFields = availableFields; - } - - return { - ...rule, - config - }; + return rule; }); - console.log('增强后的规则(首次):', enhancedRules); - setRules(enhancedRules); + // 如果没有规则或规则为空,添加一个默认规则 + if (validRules.length === 0) { + validRules.push({ id: '1', type: '', config: { availableFields } }); + } + + setRules(validRules); + } else { + // 如果rules为空或不是数组,添加一个默认规则 + setRules([{ id: '1', type: '', config: { availableFields } }]); } // 设置组合逻辑 @@ -1520,7 +1521,7 @@ export function ReviewSettings({ onChange, initialData }: ReviewSettingsProps) { break; } - // 移除只在UI使用的字段 + // 移除辅助用的UI字段 delete processedConfig.availableFields; return { @@ -1528,30 +1529,40 @@ export function ReviewSettings({ onChange, initialData }: ReviewSettingsProps) { type: rule.type, config: processedConfig }; - }) + }).filter(rule => rule.type && rule.type.trim() !== '') }; - if (onChange) { - const updateData = { - 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 - }; - - onChange(updateData); - } + // 使用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 + }); + } + }, 0); return config; }, [rules, combinationLogic, customLogic, pass_message, fail_message, suggestion_message, suggestion_message_type, post_action, action_config, score, scoreDisplay, onChange]); + // 组件初次渲染后,主动发送一次完整配置数据 + useEffect(() => { + // 如果有初始数据,在组件挂载后主动发送一次完整规则配置 + if (initialDataRef.current && onChange) { + console.log("组件挂载后发送初始完整配置"); + setTimeout(() => generateEvaluationConfig(), 100); + } + }, [generateEvaluationConfig, onChange]); + // 处理评查结果消息变更 const handleMessageChange = (type: string, value: string) => { switch(type) { diff --git a/app/routes/rules.new.tsx b/app/routes/rules.new.tsx index 4459efb..369f95c 100644 --- a/app/routes/rules.new.tsx +++ b/app/routes/rules.new.tsx @@ -174,6 +174,20 @@ interface ApiResponse { [key: string]: unknown; } +// 深拷贝工具函数 +function deepClone(obj: T): T { + if (obj === null || obj === undefined || typeof obj !== 'object') { + return obj; + } + + try { + return JSON.parse(JSON.stringify(obj)); + } catch (err) { + console.error('深拷贝对象失败:', err); + return obj; + } +} + export default function RuleNew() { const navigate = useNavigate(); const location = useLocation(); @@ -442,7 +456,7 @@ export default function RuleNew() { console.log("提取配置:", extractionConfig); console.log("评查配置:", evaluationConfig); - console.log("分数:", pointData.score); + console.log("评查规则详细信息:", JSON.stringify(evaluationConfig.rules || [], null, 2)); // 提取字段列表,用于规则设置 const extractedFields: string[] = []; @@ -548,7 +562,7 @@ export default function RuleNew() { evaluation_config: { logicType: evaluationConfig.logicType || 'and', customLogic: evaluationConfig.customLogic || '', - rules: (evaluationConfig.rules || []).map((rule) => { + rules: validateAndFixRules((evaluationConfig.rules || []).map((rule) => { // 将API规则格式转换为UI使用的格式 let config: RuleConfigType = {}; @@ -607,12 +621,17 @@ export default function RuleNew() { config = rule.config || {}; } + // 保存原始规则数据以便后续处理 + if (typeof config === 'object' && config !== null) { + config._originalData = JSON.parse(JSON.stringify(rule.config || {})); + } + return { id: rule.id, type: rule.type, config }; - }) + })) }, pass_message: pointData.pass_message || '文档检查通过,符合规范要求。', @@ -810,9 +829,12 @@ export default function RuleNew() { // 记录所有收到的数据 console.log("评查设置更新数据:", data); - // 更新规则 + // 更新规则 - 只有当明确提供了rules数据时才更新 if (data.rules) { - updatedData.evaluation_config.rules = data.rules as Rule[]; + // 验证并修复规则数据 + const validatedRules = validateAndFixRules(data.rules as Rule[]); + console.log("规则数据验证后:", validatedRules); + updatedData.evaluation_config.rules = validatedRules; } // 更新组合逻辑 @@ -866,8 +888,49 @@ export default function RuleNew() { }); }; + // 检查并修复评查规则数据,确保数据的完整性 + const validateAndFixRules = (rules: Rule[] | undefined): Rule[] => { + if (!rules || !Array.isArray(rules)) { + console.log("规则数据无效或为空,返回空数组"); + return []; + } + + // 过滤无效规则,确保每个规则都有type字段 + const validRules = rules.filter(rule => { + if (!rule || typeof rule !== 'object') { + console.log("发现无效规则对象:", rule); + return false; + } + + if (!rule.type || typeof rule.type !== 'string' || rule.type.trim() === '') { + console.log("发现无效规则类型:", rule); + return false; + } + + if (!rule.id || typeof rule.id !== 'string') { + console.log("发现缺少ID的规则:", rule); + // 为缺少ID的规则自动生成ID + rule.id = `rule_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; + } + + // 确保config存在 + if (!rule.config || typeof rule.config !== 'object') { + console.log("规则缺少配置对象,自动创建:", rule); + rule.config = {}; + } + + return true; + }); + + console.log(`规则验证结果: 输入${rules.length}条,有效${validRules.length}条`); + return validRules; + }; + // 格式化数据,准备提交到接口 const formatDataForApi = (formData: FormDataType, isDraft: boolean = false) => { + // 记录规则处理前的数据 + console.log("格式化前的评查规则数据:", formData.evaluation_config?.rules || []); + // 转换提取配置为符合数据库格式的JSON const extractionConfig = { llm: { @@ -906,11 +969,15 @@ export default function RuleNew() { } }; + // 确保规则数据有效 + const validatedRules = validateAndFixRules(formData.evaluation_config.rules || []); + console.log("验证后的评查规则数量:", validatedRules.length); + // 转换评查配置为符合数据库格式的JSON const evaluationConfig = { logicType: formData.evaluation_config.logicType || 'and', customLogic: formData.evaluation_config.customLogic || '', - rules: (formData.evaluation_config.rules || []) + rules: validatedRules .filter((rule: Rule) => rule.type && rule.type.trim() !== '') .map((rule: Rule) => { let config = {}; @@ -919,14 +986,14 @@ export default function RuleNew() { switch (rule.type) { case 'exists': config = { - fields: rule.config?.fields || [], - logic: rule.config?.logicRelation || 'and' + fields: rule.config?.fields || rule.config?.selectedFields || [], + logic: rule.config?.logic || rule.config?.logicRelation || 'and' }; break; case 'consistency': config = { pairs: rule.config?.pairs || [], - logic: rule.config?.logicRelation || 'and' + logic: rule.config?.logic || rule.config?.logicRelation || 'and' }; break; case 'format': @@ -939,7 +1006,7 @@ export default function RuleNew() { case 'logic': config = { conditions: rule.config?.conditions || [], - logic: rule.config?.logicRelation || 'and' + logic: rule.config?.logic || rule.config?.logicRelation || 'and' }; break; case 'regex': @@ -963,10 +1030,16 @@ export default function RuleNew() { }; break; default: - config = { ...rule.config }; + // 如果有保存的原始数据,优先使用 + if (rule.config?._originalData) { + config = { ...rule.config._originalData }; + } else { + config = { ...rule.config }; + } // 清除辅助字段,避免发送无效数据 if (typeof config === 'object' && config !== null) { delete (config as Record).availableFields; + delete (config as Record)._originalData; } } @@ -977,6 +1050,9 @@ export default function RuleNew() { }; }) }; + + // 记录规则处理后的数据 + console.log("处理后的评查规则数据:", evaluationConfig.rules); // 构建完整的评查点数据 const evaluationPointData: Record = { @@ -1029,6 +1105,9 @@ export default function RuleNew() { try { setIsLoading(true); + // 记录当前评查规则状态 + console.log("保存前评查规则状态:", formData.evaluation_config.rules); + // 基本验证 if (!formData.name || !formData.code) { alert("请填写评查点名称和编码,这些是必填项"); @@ -1050,14 +1129,33 @@ export default function RuleNew() { return; } - // 检查评查规则 - if (!formData.evaluation_config.rules || formData.evaluation_config.rules.length === 0 || - !formData.evaluation_config.rules.some(rule => rule.type && rule.type.trim() !== '')) { + // 检查评查规则 - 只在新增模式下检查规则是否为空 + if (!isEditMode && + (!formData.evaluation_config.rules || + formData.evaluation_config.rules.length === 0 || + !formData.evaluation_config.rules.some(rule => rule.type && rule.type.trim() !== ''))) { + console.log("规则验证失败,当前规则:", formData.evaluation_config.rules); + console.log("规则数量:", formData.evaluation_config.rules?.length || 0); + console.log("规则有效性:", formData.evaluation_config.rules?.some(rule => rule.type && rule.type.trim() !== '')); alert("请至少添加一条有效的评查规则"); setIsLoading(false); return; } + // 编辑模式下,只有当规则数组不为空时才验证规则有效性 + if (isEditMode && + formData.evaluation_config.rules && + formData.evaluation_config.rules.length > 0 && + !formData.evaluation_config.rules.some(rule => rule.type && rule.type.trim() !== '')) { + console.log("编辑模式下规则无效,当前规则:", formData.evaluation_config.rules); + console.log("编辑模式-规则数量:", formData.evaluation_config.rules.length); + console.log("编辑模式-规则详情:", JSON.stringify(formData.evaluation_config.rules, null, 2)); + console.log("编辑模式-规则有效性:", formData.evaluation_config.rules.some(rule => rule.type && rule.type.trim() !== '')); + alert("请至少添加一条有效的评查规则或清空规则列表"); + setIsLoading(false); + return; + } + const evaluationPointData = formatDataForApi(formData); console.log("保存数据:", evaluationPointData); @@ -1142,6 +1240,9 @@ export default function RuleNew() { return; } + // 编辑模式下不检查评查规则是否为空 + // 草稿模式下规则可以为空 + const draftData = formatDataForApi(formData, true); console.log("保存草稿数据:", draftData); @@ -1390,9 +1491,10 @@ export default function RuleNew() {