From dfbae3387f3225bdcf2921c252de52559fe88084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E9=B9=8F?= Date: Sat, 23 May 2026 16:29:25 +0800 Subject: [PATCH] Repair missing blueprint effect fields --- .../service/front/AiGenerateServiceImpl.java | 108 +++++++++++++++++- .../front/AiGenerateServiceImplTest.java | 39 +++++++ 2 files changed, 144 insertions(+), 3 deletions(-) diff --git a/RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerateServiceImpl.java b/RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerateServiceImpl.java index ebc3479..b07eea8 100644 --- a/RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerateServiceImpl.java +++ b/RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerateServiceImpl.java @@ -1,10 +1,13 @@ package com.ruoyi.generator.service.front; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Set; +import java.util.regex.Pattern; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -508,6 +511,7 @@ public class AiGenerateServiceImpl implements IAiGenerateService } Set actionCodes = new HashSet(); Set columnNames = collectColumnNames(response); + Map> columnNamesByTable = collectColumnNamesByTable(response); int actionIndex = 1; for (BusinessActionDesign action : response.getBusinessActions()) { @@ -524,7 +528,7 @@ public class AiGenerateServiceImpl implements IAiGenerateService action.setTransaction(action.getTransaction() == null ? Boolean.TRUE : action.getTransaction()); action.setRequestFields(normalizeExistingFieldList(action.getRequestFields(), columnNames)); action.setRules(trimStringList(action.getRules(), 200)); - normalizeBusinessEffects(action, columnNames); + normalizeBusinessEffects(action, columnNames, columnNamesByTable); actionIndex++; } } @@ -615,6 +619,32 @@ public class AiGenerateServiceImpl implements IAiGenerateService return columnNames; } + private Map> collectColumnNamesByTable(DatabaseDesignResponse response) + { + Map> columnNamesByTable = new HashMap>(); + if (response == null || response.getTables() == null) + { + return columnNamesByTable; + } + for (DatabaseTableDesign table : response.getTables()) + { + if (table == null || StringUtils.isBlank(table.getTableName()) || table.getColumns() == null) + { + continue; + } + Set tableColumnNames = new HashSet(); + for (DatabaseColumnDesign column : table.getColumns()) + { + if (column != null && StringUtils.isNotBlank(column.getColumnName())) + { + tableColumnNames.add(column.getColumnName()); + } + } + columnNamesByTable.put(table.getTableName(), tableColumnNames); + } + return columnNamesByTable; + } + private List trimStringList(List values, int maxLength) { List normalizedValues = new ArrayList(); @@ -633,13 +663,14 @@ public class AiGenerateServiceImpl implements IAiGenerateService return normalizedValues; } - private void normalizeBusinessEffects(BusinessActionDesign action, Set columnNames) + private void normalizeBusinessEffects(BusinessActionDesign action, Set columnNames, Map> columnNamesByTable) { if (action.getEffects() == null) { action.setEffects(new ArrayList()); return; } + List normalizedEffects = new ArrayList(); int effectIndex = 1; for (BusinessActionEffectDesign effect : action.getEffects()) { @@ -649,12 +680,83 @@ public class AiGenerateServiceImpl implements IAiGenerateService } effect.setType(normalizeEffectType(effect.getType(), effectIndex)); effect.setTargetTable(StringUtils.isBlank(effect.getTargetTable()) ? "" : normalizeDatabaseName(effect.getTargetTable(), "table_" + effectIndex)); - effect.setTargetField(StringUtils.isBlank(effect.getTargetField()) ? "" : normalizeDatabaseName(effect.getTargetField(), "field_" + effectIndex)); + String rawTargetField = StringUtils.isBlank(effect.getTargetField()) ? "" : normalizeDatabaseName(effect.getTargetField(), "field_" + effectIndex); + String targetField = resolveEffectTargetField(rawTargetField, effect.getTargetTable(), columnNamesByTable, columnNames); + if ("UPDATE_FIELD".equals(effect.getType()) && (StringUtils.isBlank(effect.getTargetTable()) || StringUtils.isBlank(targetField))) + { + effectIndex++; + continue; + } + effect.setTargetField(targetField); effect.setValue(trimToLength(effect.getValue(), 200)); + if (StringUtils.isNotBlank(rawTargetField) && StringUtils.isNotBlank(targetField) && !rawTargetField.equals(targetField)) + { + effect.setValue(rewriteEffectValue(effect.getValue(), rawTargetField, targetField)); + } effect.setConditionFields(normalizeExistingFieldList(effect.getConditionFields(), columnNames)); effect.setDescription(trimToLength(effect.getDescription(), 200)); + normalizedEffects.add(effect); effectIndex++; } + action.setEffects(normalizedEffects); + } + + private String resolveEffectTargetField(String targetField, String targetTable, Map> columnNamesByTable, Set columnNames) + { + if (StringUtils.isBlank(targetField)) + { + return ""; + } + Set tableColumnNames = columnNamesByTable == null ? null : columnNamesByTable.get(targetTable); + if (tableColumnNames != null) + { + if (tableColumnNames.contains(targetField)) + { + return targetField; + } + String relatedColumn = findRelatedColumn(targetField, tableColumnNames); + if (StringUtils.isNotBlank(relatedColumn)) + { + return relatedColumn; + } + } + return columnNames != null && columnNames.contains(targetField) ? targetField : ""; + } + + private String findRelatedColumn(String targetField, Set tableColumnNames) + { + if (StringUtils.isBlank(targetField) || tableColumnNames == null) + { + return ""; + } + String[] tokens = targetField.split("_"); + for (int i = tokens.length - 1; i >= 0; i--) + { + String token = tokens[i]; + if (token.length() >= 3 && tableColumnNames.contains(token)) + { + return token; + } + } + for (String columnName : tableColumnNames) + { + if (columnName.length() >= 3 && (targetField.endsWith("_" + columnName) + || targetField.startsWith(columnName + "_") || targetField.contains("_" + columnName + "_"))) + { + return columnName; + } + } + return ""; + } + + private String rewriteEffectValue(String value, String rawTargetField, String targetField) + { + String normalizedValue = trimToLength(value, 200); + if (StringUtils.isBlank(normalizedValue)) + { + return normalizedValue; + } + return normalizedValue.replaceAll("(? projectCaptor = ArgumentCaptor.forClass(FrontProject.class); + verify(frontProjectMapper).updateFrontProject(projectCaptor.capture()); + assertTrue(projectCaptor.getValue().getBusinessBlueprint().contains("\"targetField\":\"stock\"")); + assertFalse(projectCaptor.getValue().getBusinessBlueprint().contains("available_stock")); + } + @Test public void generateDatabaseRejectsBusinessActionReferencingMissingTable() { @@ -626,6 +644,27 @@ public class AiGenerateServiceImplTest + "}"; } + private String responseWithMissingBusinessEffectTargetField() + { + return "{\n" + + " \"tables\": [\n" + + " {\"tableName\": \"book_info\", \"tableComment\": \"Book info\", \"columns\": [\n" + + " {\"columnName\": \"book_id\", \"columnType\": \"bigint(20)\", \"primaryKey\": true, \"autoIncrement\": true, \"columnComment\": \"Book ID\"},\n" + + " {\"columnName\": \"stock\", \"columnType\": \"int(11)\", \"columnComment\": \"Stock\"}\n" + + " ]},\n" + + " {\"tableName\": \"borrow_record\", \"tableComment\": \"Borrow record\", \"columns\": [\n" + + " {\"columnName\": \"borrow_id\", \"columnType\": \"bigint(20)\", \"primaryKey\": true, \"autoIncrement\": true, \"columnComment\": \"Borrow ID\"},\n" + + " {\"columnName\": \"book_id\", \"columnType\": \"bigint(20)\", \"columnComment\": \"Book ID\"}\n" + + " ]}\n" + + " ],\n" + + " \"businessActions\": [\n" + + " {\"code\": \"borrow_book\", \"name\": \"Borrow Book\", \"ownerTable\": \"borrow_record\", \"method\": \"POST\", \"path\": \"/borrow\", \"requestFields\": [\"book_id\"], \"effects\": [\n" + + " {\"type\": \"UPDATE_FIELD\", \"targetTable\": \"book_info\", \"targetField\": \"available_stock\", \"value\": \"available_stock - 1\", \"conditionFields\": [\"book_id\"], \"description\": \"Decrease available stock\"}\n" + + " ]}\n" + + " ]\n" + + "}"; + } + private String responseWithMissingBusinessActionTable() { return "{\n"