FormCollectTool.java
3.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.xly.tool;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xly.service.FormResolverService;
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* FormCollect(表单呈现)—— 在对话框里渲染一张动态表单,让用户一次填多个字段(如新增记录时)。
*
* <p>字段来自 ERP 配置的知识图谱({@code viw_kg_field_dict} 里该主表最常用的可填字段),
* 前端把它们渲染成输入框;用户填完提交后,前端把「字段=值」拼成一条消息发回,agent 再走
* proposeCreate 生成待确认提议。整套 UI 在 xlyAi 自己的聊天前端完成,无需 ERP 前端配合。
*/
@Component
public class FormCollectTool {
private final FormResolverService resolver;
private final JdbcTemplate jdbc;
private final ObjectMapper mapper;
public FormCollectTool(FormResolverService resolver, JdbcTemplate jdbc, ObjectMapper mapper) {
this.resolver = resolver;
this.jdbc = jdbc;
this.mapper = mapper;
}
@Tool("在对话框里**渲染一张可填写的表单**,让用户一次性填写某实体的多个字段(用于新增记录时收集信息)。"
+ "调用后前端会显示表单;用户填完提交,你再据其内容用 proposeCreate 生成新增提议。")
public String showForm(@P("实体类型,如 客户 / 物料") String entityKeyword) {
if (entityKeyword == null || entityKeyword.isBlank()) {
return "{\"error\":\"缺少实体类型\"}";
}
Map<String, Object> form = resolver.resolveMasterForm(entityKeyword.trim());
if (form == null) {
return "{\"error\":\"找不到「" + entityKeyword + "」的主表\"}";
}
String table = String.valueOf(form.get("sDataSource"));
List<String> fields = new ArrayList<>();
Set<String> seen = new HashSet<>();
try {
List<Map<String, Object>> rows = jdbc.queryForList(
"SELECT sChinese, sField, MAX(iFormUses) u FROM viw_kg_field_dict WHERE sTable=? " +
"AND sField NOT LIKE '%Id' AND sField NOT LIKE 'b%' AND sField<>'sToken' AND sField<>'sMakePerson' " +
"AND CHAR_LENGTH(sChinese)>=2 GROUP BY sChinese, sField ORDER BY u DESC LIMIT 10", table);
for (Map<String, Object> r : rows) {
Object zh = r.get("sChinese");
if (zh != null && seen.add(zh.toString()) && fields.size() < 8) {
fields.add(zh.toString());
}
}
} catch (Exception ignore) {
}
if (fields.isEmpty()) {
return "{\"error\":\"该实体没有可填字段\"}";
}
Map<String, Object> out = new LinkedHashMap<>();
out.put("formCollect", true);
out.put("entity", entityKeyword.trim());
out.put("fields", fields);
out.put("message", "已在下方为你打开填写表单,请填好后点提交。");
try {
return mapper.writeValueAsString(out);
} catch (Exception e) {
return "{\"error\":\"内部错误\"}";
}
}
}