Commit 325d1649 authored by youxiaoji's avatar youxiaoji

+ [增加申请信息保存和提交的功能]

parent 15abfea8
...@@ -185,7 +185,7 @@ public class DefaultReactExecutor implements ReactExecutor { ...@@ -185,7 +185,7 @@ public class DefaultReactExecutor implements ReactExecutor {
memoryService.getHistoryMessages(sessionId, historyLength); memoryService.getHistoryMessages(sessionId, historyLength);
// 添加历史消息到Prompt // 添加历史消息到Prompt
// messages.addAll(historyMessages); messages.addAll(historyMessages);
// 将当前用户消息添加到内存中,以便下次对话使用 // 将当前用户消息添加到内存中,以便下次对话使用
memoryService.addUserMessageToMemory(sessionId, userInput); memoryService.addUserMessageToMemory(sessionId, userInput);
......
...@@ -4,7 +4,9 @@ import com.alibaba.fastjson2.JSON; ...@@ -4,7 +4,9 @@ import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.microsoft.playwright.*; import com.microsoft.playwright.*;
import com.microsoft.playwright.options.AriaRole;
import com.microsoft.playwright.options.Cookie; import com.microsoft.playwright.options.Cookie;
import com.microsoft.playwright.options.WaitForSelectorState;
import com.microsoft.playwright.options.WaitUntilState; import com.microsoft.playwright.options.WaitUntilState;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy; import jakarta.annotation.PreDestroy;
...@@ -23,16 +25,24 @@ import pangea.hiagent.model.UserToken; ...@@ -23,16 +25,24 @@ import pangea.hiagent.model.UserToken;
import pangea.hiagent.web.service.AgentService; import pangea.hiagent.web.service.AgentService;
import pangea.hiagent.web.service.InfoCollectorService; import pangea.hiagent.web.service.InfoCollectorService;
import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern;
@Slf4j @Slf4j
public class VisitorAppointmentTool { public class VisitorAppointmentTool {
public static final String pageId = "visitorAppointment"; public static final String pageId = "visitorAppointment";
private static final String destUrl = "https://vrms-proxy.hisense.com/ipark/hichat/#/Liteapp"; private static final String destUrl = "https://vrms-proxy.hisense.com/ipark/hichat/#/Liteapp";
private static final DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private String ssoToken; private String ssoToken;
...@@ -99,6 +109,8 @@ public class VisitorAppointmentTool { ...@@ -99,6 +109,8 @@ public class VisitorAppointmentTool {
cookies.add(ldapTokenCookie); cookies.add(ldapTokenCookie);
cookies.add(tripCookie); cookies.add(tripCookie);
sharedContext.addCookies(cookies); sharedContext.addCookies(cookies);
log.info("海信SSO认证工具的Playwright初始化成功"); log.info("海信SSO认证工具的Playwright初始化成功");
} catch (Exception e) { } catch (Exception e) {
log.error("海信SSO认证工具的Playwright初始化失败: ", e); log.error("海信SSO认证工具的Playwright初始化失败: ", e);
...@@ -127,14 +139,134 @@ public class VisitorAppointmentTool { ...@@ -127,14 +139,134 @@ public class VisitorAppointmentTool {
log.error("海信SSO认证工具的Playwright资源释放失败: ", e); log.error("海信SSO认证工具的Playwright资源释放失败: ", e);
} }
} }
@Tool(description = "提交访客预约申请")
public String submitAppointmentApply(JSONObject jsonObject){
sharedContext.tracing().start(new Tracing.StartOptions()
.setScreenshots(true)
.setSnapshots(true)
.setSources(true));
log.info("jsonObject = {}",jsonObject);
JSONArray jsonArray = infoCollectorService.getInfo(pageId);
long startTime = System.currentTimeMillis();
Page page = null;
try {
page = sharedContext.newPage();
page.setDefaultTimeout(2 * 60 * 1000);
// 访问业务系统页面
log.info("正在访问业务系统页面: {}", destUrl);
String faviconUrl = "https://vrms-proxy.hisense.com/favicon.ico";
page.navigate(faviconUrl);
page.evaluate("() => sessionStorage.setItem('Access-Token', '" + iparkToken + "')");
page.navigate(destUrl, new Page.NavigateOptions().setWaitUntil(WaitUntilState.NETWORKIDLE));
// 检查是否重定向到了SSO登录页面
String currentUrl = page.url();
log.info("当前页面URL: {}", currentUrl);
String parkValue = "";
List<JSONObject> dateJson = new ArrayList<>();
for(int i=0;i<jsonArray.size();i++){
log.info("index {} ",i);
JSONObject obj = jsonArray.getJSONObject(i);
log.info("json {}",obj);
String fieldName = obj.getString("field_name");
String fieldValue = jsonObject.getString(obj.getString("code"));
if(fieldName.compareToIgnoreCase("访问园区") == 0){
parkValue = fieldValue;
continue;
}
if(fieldName.compareToIgnoreCase("接访员工手机号")== 0 || fieldName.compareToIgnoreCase("接访员工姓名")==0){
continue;
}
if(fieldName.contains("日期")) {
dateJson.add(obj);
//fieldLocator.evaluate("el => el.value = '"+fieldValue+"'");;
}else {
Locator fieldLocator = page.locator(".van-cell")
.filter(new Locator.FilterOptions().setHasText(Pattern.compile("^" + fieldName + "$")))
.locator("input");
Locator.FillOptions fillOptions = new Locator.FillOptions();
fillOptions.setForce(true);
fieldLocator .fill(fieldValue, fillOptions);
}
//saveScreenShot(page.screenshot(),"ipark");
}
page.locator(".van-cell")
.filter(new Locator.FilterOptions().setHasText(Pattern.compile("^访问园区$")))
.locator("input").click();
Locator.WaitForOptions waitUntilOptions = new Locator.WaitForOptions();
waitUntilOptions.setState(WaitForSelectorState.ATTACHED);
page.locator(".van-overlay").waitFor(waitUntilOptions);
page.getByText(parkValue, new Page.GetByTextOptions().setExact(true)).click();
page.getByText("确认", new Page.GetByTextOptions().setExact(true)).click();
page.locator(".van-overlay").waitFor(new Locator.WaitForOptions().setState(WaitForSelectorState.HIDDEN));
for(JSONObject tmp:dateJson){
String fieldName = tmp.getString("field_name");
String fieldValue = jsonObject.getString(tmp.getString("code"));
String[] values = fieldValue.split("-");
page.locator(".van-cell")
.filter(new Locator.FilterOptions().setHasText(Pattern.compile("^"+fieldName+"$")))
.locator("input").click();
page.locator(".van-overlay").first().waitFor(waitUntilOptions);
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName(values[0]+"年")).click();
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName(values[1]+"月")).click();
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName(values[2]+"日")).click();
// 点击确认
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("确认")).click();
page.locator(".van-overlay").first().waitFor(new Locator.WaitForOptions().setState(WaitForSelectorState.HIDDEN));
}
saveScreenShot(page.screenshot(),"ipark");
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("提交"))
.click();
return "提交成功";
}catch (Exception e){
long endTime = System.currentTimeMillis();
String errorMsg = "获取海信出差申请页面内容失败: " + e.getMessage();
log.error("获取海信海信出差申请内容失败,耗时: {} ms", endTime - startTime, e);
return errorMsg;
}finally {
// 释放页面资源
if (page != null) {
try {
page.close();
} catch (Exception e) {
log.warn("关闭页面时发生异常: {}", e.getMessage());
}
}
sharedContext.tracing().stop(new Tracing.StopOptions()
.setPath(Paths.get("trace1.zip")));
}
}
private void saveScreenShot(byte[] bytes,String suffix){
// 生成一个唯一的文件名,防止覆盖
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
String fileName = "screenshot_" + timestamp +"_"+suffix+ ".png";
@Tool(description = "存储用户提交的访客预约申请信息") try {
// Paths.get() 指定存储路径,默认在项目根目录
Files.write(Paths.get(fileName), bytes);
log.info("截图已保存至: {}" , fileName);
} catch (IOException e) {
log.info("保存截图失败: " + e.getMessage());
e.printStackTrace();
}
}
@Tool(description = "保存用户提交的访客预约申请信息")
public String applyInfoSave(@ToolParam(required = true) JSONObject infos) { public String applyInfoSave(@ToolParam(required = true) JSONObject infos) {
log.info("applyInfoSave(infos={})", infos); log.info("applyInfoSave(infos={})", infos);
infos.keySet().forEach(key -> { infos.keySet().forEach(key -> {
infoCollectorService.saveValue(key, infos.get(key)); infoCollectorService.saveValue(key, infos.get(key));
}); });
Set<String> keys = infoCollectorService.findLackInfo(); Set<String> keys = infoCollectorService.findLackInfo(pageId);
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if (keys.isEmpty()) { if (keys.isEmpty()) {
sb.append("用户已提交全部数据,提示用户提交申请"); sb.append("用户已提交全部数据,提示用户提交申请");
...@@ -157,8 +289,10 @@ public class VisitorAppointmentTool { ...@@ -157,8 +289,10 @@ public class VisitorAppointmentTool {
* @return 页面内容(HTML文本) * @return 页面内容(HTML文本)
*/ */
@Tool(description = "获取访客预约申请必要信息") @Tool(description = "获取访客预约申请必要信息")
public String getTripApplyNecessaryInfo() { public String getAppointmentApplyNecessaryInfo() {
if(infoCollectorService.exists(pageId)){
return "已获取必要信息,保存用户提交的信息";
}
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
Page page = null; Page page = null;
...@@ -205,7 +339,6 @@ public class VisitorAppointmentTool { ...@@ -205,7 +339,6 @@ public class VisitorAppointmentTool {
//stringBuilder.append("从FORMSTART开始到FORMEND结束是要返回给用户的数据,直接展示给用户就可以。FORM START:"); //stringBuilder.append("从FORMSTART开始到FORMEND结束是要返回给用户的数据,直接展示给用户就可以。FORM START:");
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
jsonObject.put("FORM", jsonArray); jsonObject.put("FORM", jsonArray);
stringBuilder.append(jsonArray.toJSONString());
//stringBuilder.append("FORM END"); //stringBuilder.append("FORM END");
// 提取页面内容 // 提取页面内容
String content = stringBuilder.toString(); String content = stringBuilder.toString();
...@@ -216,7 +349,10 @@ public class VisitorAppointmentTool { ...@@ -216,7 +349,10 @@ public class VisitorAppointmentTool {
long endTime = System.currentTimeMillis(); long endTime = System.currentTimeMillis();
log.info("成功获取海信出差申请页面内容,耗时: {} ms", endTime - startTime); log.info("成功获取海信出差申请页面内容,耗时: {} ms", endTime - startTime);
log.info("用户需要提交的信息包括:{}", content); log.info("用户需要提交的信息包括:{}", content);
return "获取成功"; stringBuilder.append(formMessage.toJSONString());
stringBuilder.append("提示用户以json格式提交信息");
return stringBuilder.toString();
} catch (Exception e) { } catch (Exception e) {
long endTime = System.currentTimeMillis(); long endTime = System.currentTimeMillis();
String errorMsg = "获取海信出差申请页面内容失败: " + e.getMessage(); String errorMsg = "获取海信出差申请页面内容失败: " + e.getMessage();
......
...@@ -5,7 +5,9 @@ import com.alibaba.fastjson2.JSONObject; ...@@ -5,7 +5,9 @@ import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import pangea.hiagent.tool.impl.HisenseTripTool; import pangea.hiagent.tool.impl.HisenseTripTool;
import pangea.hiagent.tool.impl.VisitorAppointmentTool;
import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -29,7 +31,7 @@ public class InfoCollectorService { ...@@ -29,7 +31,7 @@ public class InfoCollectorService {
} }
public void saveValue(String key, Object value) { public void saveValue(String key, Object value) {
log.info("key {} value {}",key,value); log.info("key {} value {}", key, value);
values.put(key, value); values.put(key, value);
} }
...@@ -37,11 +39,27 @@ public class InfoCollectorService { ...@@ -37,11 +39,27 @@ public class InfoCollectorService {
return values.get(key); return values.get(key);
} }
public Set<String> findLackInfo() { public Set<String> findLackInfo(String pageId) {
Set<String> valueKeys = values.keySet(); Set<String> valueKeys = values.keySet();
Set<String> allKeys = infos.get(HisenseTripTool.pageId).stream().map(t -> ((JSONObject) t).getString("field_name")).collect(Collectors.toSet()); log.info("value keys {}", valueKeys);
Set<String> allKeys = infos.get(pageId).stream().map(t -> ((JSONObject) t).getString("code")).collect(Collectors.toSet());
log.info("all keys {}", allKeys);
allKeys.removeAll(valueKeys); allKeys.removeAll(valueKeys);
log.info("lack keys {}", allKeys); log.info("lack keys {}", allKeys);
return allKeys; Set<String> lackInfos = new HashSet<>();
if(lackInfos.isEmpty()){
log.info("info is good enough");
return lackInfos;
}
infos.get(pageId).stream().forEach(t ->
{
JSONObject info = (JSONObject) t;
String code = info.getString("code");
if (allKeys.contains(code)) {
lackInfos.add(info.getString("field_name"));
}
});
log.info("lack infos {}", lackInfos);
return lackInfos;
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment