Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Pangea-Agent
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
2
Merge Requests
2
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Gavin-Group
Pangea-Agent
Commits
d2f8d7c9
Commit
d2f8d7c9
authored
Dec 31, 2025
by
高如斌
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop_tmp' into 'feature/chat-form'
Develop tmp See merge request
!7
parents
a2b3a8c8
1ff00b03
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
165 additions
and
112 deletions
+165
-112
pom.xml
backend/pom.xml
+10
-0
DefaultReactExecutor.java
...java/pangea/hiagent/agent/react/DefaultReactExecutor.java
+22
-21
VisitorAppointmentTool.java
...java/pangea/hiagent/tool/impl/VisitorAppointmentTool.java
+30
-22
PlaywrightManagerImpl.java
...pangea/hiagent/tool/playwright/PlaywrightManagerImpl.java
+77
-59
AgentDialogueRepository.java
...angea/hiagent/web/repository/AgentDialogueRepository.java
+4
-0
ChatService.java
...src/main/java/pangea/hiagent/web/service/ChatService.java
+6
-0
InfoCollectorService.java
...java/pangea/hiagent/web/service/InfoCollectorService.java
+5
-5
application-dev.yml
backend/src/main/resources/application-dev.yml
+5
-5
vite.config.ts
frontend/vite.config.ts
+6
-0
No files found.
backend/pom.xml
View file @
d2f8d7c9
...
@@ -338,6 +338,16 @@
...
@@ -338,6 +338,16 @@
<artifactId>
lombok
</artifactId>
<artifactId>
lombok
</artifactId>
</exclude>
</exclude>
</excludes>
</excludes>
<requiresUnpack>
<dependency>
<groupId>
com.microsoft.playwright
</groupId>
<artifactId>
driver
</artifactId>
</dependency>
<dependency>
<groupId>
com.microsoft.playwright
</groupId>
<artifactId>
driver-bundle
</artifactId>
</dependency>
</requiresUnpack>
</configuration>
</configuration>
</plugin>
</plugin>
...
...
backend/src/main/java/pangea/hiagent/agent/react/DefaultReactExecutor.java
View file @
d2f8d7c9
...
@@ -125,29 +125,26 @@ public class DefaultReactExecutor implements ReactExecutor {
...
@@ -125,29 +125,26 @@ public class DefaultReactExecutor implements ReactExecutor {
List
<
org
.
springframework
.
ai
.
chat
.
messages
.
Message
>
messages
=
new
ArrayList
<>();
List
<
org
.
springframework
.
ai
.
chat
.
messages
.
Message
>
messages
=
new
ArrayList
<>();
messages
.
add
(
new
SystemMessage
(
systemPrompt
));
messages
.
add
(
new
SystemMessage
(
systemPrompt
));
if
(!
newChat
)
{
if
(
agent
!=
null
)
{
try
{
// 如果没有提供用户ID,则尝试获取当前用户ID
if
(
userId
==
null
)
{
userId
=
UserUtils
.
getCurrentUserIdStatic
();
}
String
sessionId
=
memoryService
.
generateSessionId
(
agent
,
userId
);
if
(
agent
!=
null
)
{
int
historyLength
=
agent
.
getHistoryLength
()
!=
null
?
agent
.
getHistoryLength
()
:
10
;
try
{
// 如果没有提供用户ID,则尝试获取当前用户ID
if
(
userId
==
null
)
{
userId
=
UserUtils
.
getCurrentUserIdStatic
();
}
String
sessionId
=
memoryService
.
generateSessionId
(
agent
,
userId
);
int
historyLength
=
agent
.
getHistoryLength
()
!=
null
?
agent
.
getHistoryLength
()
:
10
;
List
<
org
.
springframework
.
ai
.
chat
.
messages
.
Message
>
historyMessages
=
List
<
org
.
springframework
.
ai
.
chat
.
messages
.
Message
>
historyMessages
=
memoryService
.
getHistoryMessages
(
sessionId
,
historyLength
);
memoryService
.
getHistoryMessages
(
sessionId
,
historyLength
);
if
(!
newChat
)
{
messages
.
addAll
(
historyMessages
);
messages
.
addAll
(
historyMessages
);
memoryService
.
addUserMessageToMemory
(
sessionId
,
userInput
);
}
catch
(
Exception
e
)
{
log
.
warn
(
"获取历史对话记录时发生错误: {}"
,
e
.
getMessage
());
}
}
memoryService
.
addUserMessageToMemory
(
sessionId
,
userInput
);
}
catch
(
Exception
e
)
{
log
.
warn
(
"获取历史对话记录时发生错误: {}"
,
e
.
getMessage
());
}
}
}
}
messages
.
add
(
new
UserMessage
(
userInput
));
messages
.
add
(
new
UserMessage
(
userInput
));
for
(
Message
message
:
messages
)
{
for
(
Message
message
:
messages
)
{
log
.
info
(
"message is {}"
,
message
);
log
.
info
(
"message is {}"
,
message
);
...
@@ -179,13 +176,17 @@ public class DefaultReactExecutor implements ReactExecutor {
...
@@ -179,13 +176,17 @@ public class DefaultReactExecutor implements ReactExecutor {
log
.
info
(
"agentTools {}"
,
agentTools
);
log
.
info
(
"agentTools {}"
,
agentTools
);
if
(
agent
.
getId
().
compareToIgnoreCase
(
"agent-8"
)
==
0
)
{
if
(
agent
.
getId
().
compareToIgnoreCase
(
"agent-8"
)
==
0
)
{
if
(!
chatService
.
chatExists
(
tmpUserId
,
agent
.
getId
()))
{
boolean
chatExists
=
chatService
.
chatExists
(
tmpUserId
,
agent
.
getId
());
log
.
info
(
"new chat for {} {} "
,
userId
,
agent
.
getId
());
String
newChat
=
"yes"
;
prompt
=
buildPromptWithHistory
(
defaultSystemPrompt
,
userInput
,
agent
,
tmpUserId
,
true
);
if
(
chatExists
){
newChat
=
"no"
;
}
}
// log.info("new chat for {} {} ", userId, agent.getId());
prompt
=
buildPromptWithHistory
(
agent
.
getSystemPrompt
(),
userInput
,
agent
,
tmpUserId
,
true
);
//}
chatClient
.
prompt
(
prompt
)
chatClient
.
prompt
(
prompt
)
.
tools
(
agentTools
.
toArray
())
.
tools
(
agentTools
.
toArray
())
.
toolContext
(
Map
.
of
(
"emitterId"
,
emitterId
,
"userId"
,
sseTokenEmitter
.
getUserId
(),
"agentId"
,
agent
.
getId
()
))
.
toolContext
(
Map
.
of
(
"emitterId"
,
emitterId
,
"userId"
,
sseTokenEmitter
.
getUserId
(),
"agentId"
,
agent
.
getId
(),
"newChat"
,
newChat
))
.
stream
()
.
stream
()
.
chatResponse
()
.
chatResponse
()
.
subscribe
(
.
subscribe
(
...
...
backend/src/main/java/pangea/hiagent/tool/impl/VisitorAppointmentTool.java
View file @
d2f8d7c9
...
@@ -75,7 +75,7 @@ public class VisitorAppointmentTool {
...
@@ -75,7 +75,7 @@ public class VisitorAppointmentTool {
// 登录状态有效期(毫秒),设置为30分钟
// 登录状态有效期(毫秒),设置为30分钟
private
static
final
long
LOGIN_VALIDITY_PERIOD
=
30
*
60
*
1000
;
private
static
final
long
LOGIN_VALIDITY_PERIOD
=
30
*
60
*
1000
;
public
VisitorAppointmentTool
(
UserTokenService
userTokenService
,
AgentService
agentService
,
InfoCollectorService
infoCollectorService
,
UserSseService
userSseService
,
ChatService
chatService
)
{
public
VisitorAppointmentTool
(
UserTokenService
userTokenService
,
AgentService
agentService
,
InfoCollectorService
infoCollectorService
,
UserSseService
userSseService
,
ChatService
chatService
)
{
this
.
agentService
=
agentService
;
this
.
agentService
=
agentService
;
this
.
infoCollectorService
=
infoCollectorService
;
this
.
infoCollectorService
=
infoCollectorService
;
this
.
ssoToken
=
"33f667865c395f164d29487c15fe74bf76b463f2941ef6af55d14a35a11d60b1"
;
this
.
ssoToken
=
"33f667865c395f164d29487c15fe74bf76b463f2941ef6af55d14a35a11d60b1"
;
...
@@ -141,10 +141,11 @@ public class VisitorAppointmentTool {
...
@@ -141,10 +141,11 @@ public class VisitorAppointmentTool {
log
.
error
(
"海信SSO认证工具的Playwright资源释放失败: "
,
e
);
log
.
error
(
"海信SSO认证工具的Playwright资源释放失败: "
,
e
);
}
}
}
}
private
String
setAccessToken
(
ToolContext
toolContext
)
{
private
String
setAccessToken
(
ToolContext
toolContext
)
{
String
userId
=
toolContext
.
getContext
().
get
(
"userId"
).
toString
();
String
userId
=
toolContext
.
getContext
().
get
(
"userId"
).
toString
();
log
.
info
(
"start set access token for {}"
,
userId
);
log
.
info
(
"start set access token for {}"
,
userId
);
UserToken
userToken
=
userTokenService
.
getUserToken
(
userId
,
"pangea"
);
UserToken
userToken
=
userTokenService
.
getUserToken
(
userId
,
"pangea"
);
Cookie
tripCookie
=
new
Cookie
(
"jwtToken"
,
userToken
.
getTokenValue
());
Cookie
tripCookie
=
new
Cookie
(
"jwtToken"
,
userToken
.
getTokenValue
());
tripCookie
.
setDomain
(
"vrms-proxy.hisense.com"
);
tripCookie
.
setDomain
(
"vrms-proxy.hisense.com"
);
tripCookie
.
setPath
(
"/"
);
tripCookie
.
setPath
(
"/"
);
...
@@ -165,8 +166,6 @@ public class VisitorAppointmentTool {
...
@@ -165,8 +166,6 @@ public class VisitorAppointmentTool {
// .setSources(true));
// .setSources(true));
log
.
info
(
"submit apply info "
);
log
.
info
(
"submit apply info "
);
String
accessToken
=
setAccessToken
(
toolContext
);
String
accessToken
=
setAccessToken
(
toolContext
);
JSONArray
jsonArray
=
infoCollectorService
.
getInfo
(
pageId
);
JSONArray
jsonArray
=
infoCollectorService
.
getInfo
(
pageId
);
...
@@ -196,8 +195,8 @@ public class VisitorAppointmentTool {
...
@@ -196,8 +195,8 @@ public class VisitorAppointmentTool {
log
.
info
(
"json {}"
,
obj
);
log
.
info
(
"json {}"
,
obj
);
String
fieldName
=
obj
.
getString
(
"field_name"
);
String
fieldName
=
obj
.
getString
(
"field_name"
);
String
fieldValue
=
infoCollectorService
.
getValue
(
obj
.
getString
(
"code"
)
).
toString
();
String
fieldValue
=
infoCollectorService
.
getValue
(
fieldName
).
toString
();
log
.
info
(
"fieldName {} fieldValue {} "
,
fieldName
,
fieldValue
);
log
.
info
(
"fieldName {} fieldValue {} "
,
fieldName
,
fieldValue
);
if
(
fieldName
.
compareToIgnoreCase
(
"访问园区"
)
==
0
)
{
if
(
fieldName
.
compareToIgnoreCase
(
"访问园区"
)
==
0
)
{
parkValue
=
fieldValue
;
parkValue
=
fieldValue
;
continue
;
continue
;
...
@@ -234,7 +233,7 @@ public class VisitorAppointmentTool {
...
@@ -234,7 +233,7 @@ public class VisitorAppointmentTool {
for
(
JSONObject
tmp
:
dateJson
)
{
for
(
JSONObject
tmp
:
dateJson
)
{
String
fieldName
=
tmp
.
getString
(
"field_name"
);
String
fieldName
=
tmp
.
getString
(
"field_name"
);
String
fieldValue
=
infoCollectorService
.
getValue
(
tmp
.
getString
(
"code"
)
).
toString
();
String
fieldValue
=
infoCollectorService
.
getValue
(
fieldName
).
toString
();
String
[]
values
=
fieldValue
.
split
(
"-"
);
String
[]
values
=
fieldValue
.
split
(
"-"
);
page
.
locator
(
".van-cell"
)
page
.
locator
(
".van-cell"
)
...
@@ -308,7 +307,7 @@ public class VisitorAppointmentTool {
...
@@ -308,7 +307,7 @@ public class VisitorAppointmentTool {
infoCollectorService
.
saveValue
(
key
,
infos
.
get
(
key
));
infoCollectorService
.
saveValue
(
key
,
infos
.
get
(
key
));
});
});
infoCollectorService
.
saveDefaultValue
(
pageId
);
infoCollectorService
.
saveDefaultValue
(
pageId
);
Map
<
String
,
String
>
keys
=
infoCollectorService
.
findLackInfo
(
pageId
);
Map
<
String
,
String
>
keys
=
infoCollectorService
.
findLackInfo
(
pageId
);
if
(!
keys
.
isEmpty
())
{
if
(!
keys
.
isEmpty
())
{
JSONArray
jsonArray
=
infoCollectorService
.
getInfo
(
pageId
);
JSONArray
jsonArray
=
infoCollectorService
.
getInfo
(
pageId
);
JSONArray
lackJson
=
new
JSONArray
();
JSONArray
lackJson
=
new
JSONArray
();
...
@@ -316,8 +315,12 @@ public class VisitorAppointmentTool {
...
@@ -316,8 +315,12 @@ public class VisitorAppointmentTool {
for
(
int
i
=
0
;
i
<
jsonArray
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
jsonArray
.
size
();
i
++)
{
JSONObject
tmp
=
jsonArray
.
getJSONObject
(
i
);
JSONObject
tmp
=
jsonArray
.
getJSONObject
(
i
);
JSONObject
pangeJson
=
tmp
.
getJSONObject
(
"pangea_json"
);
JSONObject
pangeJson
=
tmp
.
getJSONObject
(
"pangea_json"
);
if
(
infoCollectorService
.
getValue
(
tmp
.
getString
(
"code"
))
!=
null
){
if
(
infoCollectorService
.
getValue
(
tmp
.
getString
(
"field_name"
))
!=
null
)
{
pangeJson
.
getJSONObject
(
"props"
).
put
(
"value"
,
infoCollectorService
.
getValue
(
tmp
.
getString
(
"code"
)).
toString
());
pangeJson
.
getJSONObject
(
"props"
).
put
(
"value"
,
infoCollectorService
.
getValue
(
tmp
.
getString
(
"field_name"
)).
toString
());
}
if
(
tmp
.
getString
(
"field_name"
).
compareToIgnoreCase
(
"接访员工手机号"
)
==
0
||
tmp
.
getString
(
"field_name"
).
compareToIgnoreCase
(
"接访员工姓名"
)
==
0
)
{
continue
;
}
}
lackJson
.
add
(
pangeJson
);
lackJson
.
add
(
pangeJson
);
}
}
...
@@ -331,18 +334,15 @@ public class VisitorAppointmentTool {
...
@@ -331,18 +334,15 @@ public class VisitorAppointmentTool {
}
else
{
}
else
{
sb
.
append
(
"用户还有以下信息未提交:"
);
sb
.
append
(
"用户还有以下信息未提交:"
);
sb
.
append
(
"\n"
);
sb
.
append
(
"\n"
);
for
(
Map
.
Entry
<
String
,
String
>
key
:
keys
.
entrySet
())
{
for
(
Map
.
Entry
<
String
,
String
>
key
:
keys
.
entrySet
())
{
sb
.
append
(
key
.
getValue
());
sb
.
append
(
key
.
getValue
());
sb
.
append
(
"("
);
sb
.
append
(
key
);
sb
.
append
(
")"
);
sb
.
append
(
","
);
sb
.
append
(
","
);
sb
.
append
(
"\n"
);
}
}
sb
.
append
(
"\n"
);
sb
.
append
(
"提示用户继续提交信息"
);
sb
.
append
(
"提示用户继续提交信息"
);
}
}
log
.
info
(
"notice {}"
,
sb
.
toString
());
log
.
info
(
"notice {}"
,
sb
.
toString
());
return
sb
.
toString
();
return
sb
.
toString
();
}
}
...
@@ -367,14 +367,22 @@ public class VisitorAppointmentTool {
...
@@ -367,14 +367,22 @@ public class VisitorAppointmentTool {
JSONArray
lackJson
=
new
JSONArray
();
JSONArray
lackJson
=
new
JSONArray
();
for
(
int
i
=
0
;
i
<
jsonArray
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
jsonArray
.
size
();
i
++)
{
JSONObject
tmp
=
jsonArray
.
getJSONObject
(
i
);
JSONObject
tmp
=
jsonArray
.
getJSONObject
(
i
);
if
(
tmp
.
getString
(
"field_name"
).
compareToIgnoreCase
(
"接访员工手机号"
)
==
0
||
tmp
.
getString
(
"field_name"
).
compareToIgnoreCase
(
"接访员工姓名"
)
==
0
)
{
continue
;
}
lackJson
.
add
(
tmp
.
getJSONObject
(
"pangea_json"
));
lackJson
.
add
(
tmp
.
getJSONObject
(
"pangea_json"
));
}
}
JSONObject
formMessage
=
new
JSONObject
();
JSONObject
formMessage
=
new
JSONObject
();
formMessage
.
put
(
"coms"
,
lackJson
);
formMessage
.
put
(
"coms"
,
lackJson
);
try
{
boolean
newChat
=
toolContext
.
getContext
().
get
(
"newChat"
).
toString
().
compareToIgnoreCase
(
"yes"
)
==
0
;
sendFormMessage
(
formMessage
,
toolContext
);
log
.
info
(
"new chat {}"
,
newChat
);
}
catch
(
Exception
e
)
{
if
(
newChat
)
{
e
.
printStackTrace
();
try
{
sendFormMessage
(
formMessage
,
toolContext
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
}
stringBuilder
.
append
(
formMessage
.
toJSONString
());
stringBuilder
.
append
(
formMessage
.
toJSONString
());
stringBuilder
.
append
(
"提示用户以json格式提交信息;如果用户已提供部分信息,需要将这些信息与`props.name`属性的值进行匹配,并将匹配之后的信息以json格式提交到`applyInfoSave`以保存信息"
);
stringBuilder
.
append
(
"提示用户以json格式提交信息;如果用户已提供部分信息,需要将这些信息与`props.name`属性的值进行匹配,并将匹配之后的信息以json格式提交到`applyInfoSave`以保存信息"
);
...
@@ -420,8 +428,8 @@ public class VisitorAppointmentTool {
...
@@ -420,8 +428,8 @@ public class VisitorAppointmentTool {
JSONArray
result
=
new
JSONArray
();
JSONArray
result
=
new
JSONArray
();
for
(
int
i
=
0
;
i
<
jsonArray
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
jsonArray
.
size
();
i
++)
{
JSONObject
tmp
=
jsonArray
.
getJSONObject
(
i
);
JSONObject
tmp
=
jsonArray
.
getJSONObject
(
i
);
if
(
tmp
.
getString
(
"field_name"
).
compareToIgnoreCase
(
"接访员工手机号"
)
==
0
if
(
tmp
.
getString
(
"field_name"
).
compareToIgnoreCase
(
"接访员工手机号"
)
==
0
||
tmp
.
getString
(
"field_name"
).
compareToIgnoreCase
(
"接访员工姓名"
)
==
0
)
{
||
tmp
.
getString
(
"field_name"
).
compareToIgnoreCase
(
"接访员工姓名"
)
==
0
)
{
continue
;
continue
;
}
}
result
.
add
(
tmp
);
result
.
add
(
tmp
);
...
...
backend/src/main/java/pangea/hiagent/tool/playwright/PlaywrightManagerImpl.java
View file @
d2f8d7c9
...
@@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j;
...
@@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Component
;
import
jakarta.annotation.PreDestroy
;
import
jakarta.annotation.PreDestroy
;
import
java.util.concurrent.*
;
import
java.util.concurrent.*
;
/**
/**
...
@@ -14,36 +15,35 @@ import java.util.concurrent.*;
...
@@ -14,36 +15,35 @@ import java.util.concurrent.*;
@Slf4j
@Slf4j
@Component
// Spring默认单例模式
@Component
// Spring默认单例模式
public
class
PlaywrightManagerImpl
implements
PlaywrightManager
{
public
class
PlaywrightManagerImpl
implements
PlaywrightManager
{
// 共享的Playwright实例
// 共享的Playwright实例
private
volatile
Playwright
playwright
;
private
volatile
Playwright
playwright
;
// 共享的浏览器实例
// 共享的浏览器实例
private
volatile
Browser
browser
;
private
volatile
Browser
browser
;
// 用户浏览器上下文映射表(用户ID -> BrowserContext)
// 用户浏览器上下文映射表(用户ID -> BrowserContext)
private
final
ConcurrentMap
<
String
,
BrowserContext
>
userContexts
=
new
ConcurrentHashMap
<>();
private
final
ConcurrentMap
<
String
,
BrowserContext
>
userContexts
=
new
ConcurrentHashMap
<>();
// 用户上下文创建时间映射表(用于超时清理)
// 用户上下文创建时间映射表(用于超时清理)
private
final
ConcurrentMap
<
String
,
Long
>
contextCreationTimes
=
new
ConcurrentHashMap
<>();
private
final
ConcurrentMap
<
String
,
Long
>
contextCreationTimes
=
new
ConcurrentHashMap
<>();
// 用户上下文超时时间(毫秒),默认30分钟
// 用户上下文超时时间(毫秒),默认30分钟
private
static
final
long
CONTEXT_TIMEOUT
=
30
*
60
*
1000
;
private
static
final
long
CONTEXT_TIMEOUT
=
30
*
60
*
1000
;
// 清理任务调度器
// 清理任务调度器
private
final
ScheduledExecutorService
cleanupScheduler
=
private
final
ScheduledExecutorService
cleanupScheduler
=
Executors
.
newSingleThreadScheduledExecutor
(
r
->
{
Executors
.
newSingleThreadScheduledExecutor
(
r
->
{
Thread
t
=
new
Thread
(
r
,
"PlaywrightCleanupScheduler"
);
Thread
t
=
new
Thread
(
r
,
"PlaywrightCleanupScheduler"
);
t
.
setDaemon
(
true
);
// 设置为守护线程
t
.
setDaemon
(
true
);
// 设置为守护线程
return
t
;
return
t
;
});
});
// 标记是否已经初始化
// 标记是否已经初始化
private
volatile
boolean
initialized
=
false
;
private
volatile
boolean
initialized
=
false
;
// 用于同步初始化过程
// 用于同步初始化过程
private
final
Object
initLock
=
new
Object
();
private
final
Object
initLock
=
new
Object
();
/**
/**
* 延迟初始化Playwright和浏览器实例
* 延迟初始化Playwright和浏览器实例
*/
*/
...
@@ -53,23 +53,38 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
...
@@ -53,23 +53,38 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
if
(!
initialized
)
{
if
(!
initialized
)
{
try
{
try
{
log
.
info
(
"正在初始化Playwright管理器..."
);
log
.
info
(
"正在初始化Playwright管理器..."
);
// 创建Playwright实例
// 创建Playwright实例
this
.
playwright
=
Playwright
.
create
();
if
(
playwright
==
null
)
{
this
.
playwright
=
Playwright
.
create
();
// 启动Chrome浏览器,无头模式
}
this
.
browser
=
playwright
.
chromium
().
launch
(
new
BrowserType
.
LaunchOptions
()
if
(
browser
==
null
)
{
.
setHeadless
(
true
)
// 启动Chrome浏览器,无头模式
.
setArgs
(
java
.
util
.
Arrays
.
asList
(
this
.
browser
=
playwright
.
chromium
().
launch
(
new
BrowserType
.
LaunchOptions
()
"--no-sandbox"
,
.
setHeadless
(
true
)
"--disable-dev-shm-usage"
,
.
setArgs
(
java
.
util
.
Arrays
.
asList
(
"--disable-gpu"
,
"--no-sandbox"
,
"--remote-allow-origins=*"
)));
"--disable-dev-shm-usage"
,
"--disable-gpu"
,
"--remote-allow-origins=*"
)));
this
.
browser
.
onDisconnected
((
browser
)
->
{
log
.
info
(
"浏览器实例已断开连接"
);
this
.
browser
.
close
();
userContexts
.
clear
();
this
.
browser
=
playwright
.
chromium
().
launch
(
new
BrowserType
.
LaunchOptions
()
.
setHeadless
(
true
)
.
setArgs
(
java
.
util
.
Arrays
.
asList
(
"--no-sandbox"
,
"--disable-dev-shm-usage"
,
"--disable-gpu"
,
"--remote-allow-origins=*"
)));
});
}
// 每5分钟检查一次超时的用户上下文
// 每5分钟检查一次超时的用户上下文
cleanupScheduler
.
scheduleAtFixedRate
(
this
::
cleanupExpiredContexts
,
cleanupScheduler
.
scheduleAtFixedRate
(
this
::
cleanupExpiredContexts
,
5
,
5
,
TimeUnit
.
MINUTES
);
5
,
3600
,
TimeUnit
.
MINUTES
);
this
.
initialized
=
true
;
this
.
initialized
=
true
;
log
.
info
(
"Playwright管理器初始化成功"
);
log
.
info
(
"Playwright管理器初始化成功"
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
...
@@ -80,15 +95,15 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
...
@@ -80,15 +95,15 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
}
}
}
}
}
}
// 移除@PostConstruct注解,避免在Spring初始化时自动调用
// 移除@PostConstruct注解,避免在Spring初始化时自动调用
/*
/*
@PostConstruct
*
@PostConstruct
public void initialize() {
*
public void initialize() {
lazyInitialize();
*
lazyInitialize();
}
*
}
*/
*/
@Override
@Override
public
Playwright
getPlaywright
()
{
public
Playwright
getPlaywright
()
{
lazyInitialize
();
lazyInitialize
();
...
@@ -97,7 +112,7 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
...
@@ -97,7 +112,7 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
}
}
return
playwright
;
return
playwright
;
}
}
@Override
@Override
public
Browser
getBrowser
()
{
public
Browser
getBrowser
()
{
lazyInitialize
();
lazyInitialize
();
...
@@ -106,30 +121,33 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
...
@@ -106,30 +121,33 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
}
}
return
browser
;
return
browser
;
}
}
@Override
@Override
public
BrowserContext
getUserContext
(
String
userId
)
{
public
BrowserContext
getUserContext
(
String
userId
)
{
lazyInitialize
();
lazyInitialize
();
Browser
.
NewContextOptions
options
=
new
Browser
.
NewContextOptions
()
Browser
.
NewContextOptions
options
=
new
Browser
.
NewContextOptions
()
.
setViewportSize
(
1920
,
1080
)
// 设置视口大小为全高清分辨率,适用于Windows 11桌面环境
.
setViewportSize
(
1920
,
1080
)
// 设置视口大小为全高清分辨率,适用于Windows 11桌面环境
.
setUserAgent
(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
);
// 设置用户代理为Windows 11 Chrome浏览器
.
setUserAgent
(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
);
// 设置用户代理为Windows
// 11
// Chrome浏览器
return
getUserContext
(
userId
,
options
);
return
getUserContext
(
userId
,
options
);
}
}
@Override
@Override
public
BrowserContext
getUserContext
(
String
userId
,
Browser
.
NewContextOptions
options
)
{
public
BrowserContext
getUserContext
(
String
userId
,
Browser
.
NewContextOptions
options
)
{
lazyInitialize
();
lazyInitialize
();
if
(
userId
==
null
||
userId
.
isEmpty
())
{
if
(
userId
==
null
||
userId
.
isEmpty
())
{
throw
new
IllegalArgumentException
(
"User ID cannot be null or empty"
);
throw
new
IllegalArgumentException
(
"User ID cannot be null or empty"
);
}
}
if
(
options
==
null
)
{
if
(
options
==
null
)
{
options
=
new
Browser
.
NewContextOptions
();
options
=
new
Browser
.
NewContextOptions
();
}
}
// 尝试从缓存中获取已存在的上下文
// 尝试从缓存中获取已存在的上下文
BrowserContext
context
=
userContexts
.
get
(
userId
);
BrowserContext
context
=
userContexts
.
get
(
userId
);
// 如果上下文不存在或已关闭,则创建新的
// 如果上下文不存在或已关闭,则创建新的
if
(
context
==
null
||
isContextClosed
(
context
))
{
if
(
context
==
null
||
isContextClosed
(
context
))
{
try
{
try
{
...
@@ -142,19 +160,19 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
...
@@ -142,19 +160,19 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
throw
new
RuntimeException
(
"Failed to create browser context for user: "
+
userId
,
e
);
throw
new
RuntimeException
(
"Failed to create browser context for user: "
+
userId
,
e
);
}
}
}
}
return
context
;
return
context
;
}
}
@Override
@Override
public
void
releaseUserContext
(
String
userId
)
{
public
void
releaseUserContext
(
String
userId
)
{
if
(
userId
==
null
||
userId
.
isEmpty
())
{
if
(
userId
==
null
||
userId
.
isEmpty
())
{
return
;
return
;
}
}
BrowserContext
context
=
userContexts
.
remove
(
userId
);
BrowserContext
context
=
userContexts
.
remove
(
userId
);
contextCreationTimes
.
remove
(
userId
);
contextCreationTimes
.
remove
(
userId
);
if
(
context
!=
null
)
{
if
(
context
!=
null
)
{
try
{
try
{
context
.
close
();
context
.
close
();
...
@@ -164,10 +182,10 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
...
@@ -164,10 +182,10 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
}
}
}
}
}
}
/**
/**
* 检查BrowserContext是否已关闭
* 检查BrowserContext是否已关闭
*
*
* @param context 要检查的BrowserContext
* @param context 要检查的BrowserContext
* @return 如果上下文已关闭则返回true,否则返回false
* @return 如果上下文已关闭则返回true,否则返回false
*/
*/
...
@@ -182,14 +200,14 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
...
@@ -182,14 +200,14 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
return
true
;
return
true
;
}
}
}
}
/**
/**
* 清理过期的用户上下文
* 清理过期的用户上下文
*/
*/
private
void
cleanupExpiredContexts
()
{
private
void
cleanupExpiredContexts
()
{
long
currentTime
=
System
.
currentTimeMillis
();
long
currentTime
=
System
.
currentTimeMillis
();
long
expiredThreshold
=
currentTime
-
CONTEXT_TIMEOUT
;
long
expiredThreshold
=
currentTime
-
CONTEXT_TIMEOUT
;
for
(
String
userId
:
contextCreationTimes
.
keySet
())
{
for
(
String
userId
:
contextCreationTimes
.
keySet
())
{
Long
creationTime
=
contextCreationTimes
.
get
(
userId
);
Long
creationTime
=
contextCreationTimes
.
get
(
userId
);
if
(
creationTime
!=
null
&&
creationTime
<
expiredThreshold
)
{
if
(
creationTime
!=
null
&&
creationTime
<
expiredThreshold
)
{
...
@@ -198,7 +216,7 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
...
@@ -198,7 +216,7 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
}
}
}
}
}
}
/**
/**
* 销毁所有资源
* 销毁所有资源
*/
*/
...
@@ -206,7 +224,7 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
...
@@ -206,7 +224,7 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
@Override
@Override
public
void
destroy
()
{
public
void
destroy
()
{
log
.
info
(
"开始销毁Playwright管理器资源..."
);
log
.
info
(
"开始销毁Playwright管理器资源..."
);
try
{
try
{
// 关闭清理任务调度器
// 关闭清理任务调度器
cleanupScheduler
.
shutdown
();
cleanupScheduler
.
shutdown
();
...
@@ -216,12 +234,12 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
...
@@ -216,12 +234,12 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
log
.
warn
(
"关闭清理任务调度器时发生异常"
,
e
);
log
.
warn
(
"关闭清理任务调度器时发生异常"
,
e
);
}
}
// 关闭所有用户上下文
// 关闭所有用户上下文
for
(
String
userId
:
userContexts
.
keySet
())
{
for
(
String
userId
:
userContexts
.
keySet
())
{
releaseUserContext
(
userId
);
releaseUserContext
(
userId
);
}
}
// 关闭浏览器
// 关闭浏览器
try
{
try
{
if
(
browser
!=
null
&&
browser
.
isConnected
())
{
if
(
browser
!=
null
&&
browser
.
isConnected
())
{
...
@@ -231,7 +249,7 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
...
@@ -231,7 +249,7 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
log
.
warn
(
"关闭浏览器实例时发生异常"
,
e
);
log
.
warn
(
"关闭浏览器实例时发生异常"
,
e
);
}
}
// 关闭Playwright
// 关闭Playwright
try
{
try
{
if
(
playwright
!=
null
)
{
if
(
playwright
!=
null
)
{
...
@@ -241,7 +259,7 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
...
@@ -241,7 +259,7 @@ public class PlaywrightManagerImpl implements PlaywrightManager {
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
log
.
warn
(
"关闭Playwright实例时发生异常"
,
e
);
log
.
warn
(
"关闭Playwright实例时发生异常"
,
e
);
}
}
log
.
info
(
"Playwright管理器资源已全部销毁"
);
log
.
info
(
"Playwright管理器资源已全部销毁"
);
}
}
}
}
\ No newline at end of file
backend/src/main/java/pangea/hiagent/web/repository/AgentDialogueRepository.java
View file @
d2f8d7c9
package
pangea
.
hiagent
.
web
.
repository
;
package
pangea
.
hiagent
.
web
.
repository
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
org.apache.ibatis.annotations.Delete
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Select
;
import
pangea.hiagent.model.AgentDialogue
;
import
pangea.hiagent.model.AgentDialogue
;
/**
/**
...
@@ -9,4 +11,6 @@ import pangea.hiagent.model.AgentDialogue;
...
@@ -9,4 +11,6 @@ import pangea.hiagent.model.AgentDialogue;
*/
*/
@Mapper
@Mapper
public
interface
AgentDialogueRepository
extends
BaseMapper
<
AgentDialogue
>
{
public
interface
AgentDialogueRepository
extends
BaseMapper
<
AgentDialogue
>
{
@Delete
(
"DELETE FROM agent_dialogue WHERE user_id = #{userId} AND agent_id=#{agentId} "
)
public
void
deleteDialogue
(
String
userId
,
String
agentId
);
}
}
backend/src/main/java/pangea/hiagent/web/service/ChatService.java
View file @
d2f8d7c9
package
pangea
.
hiagent
.
web
.
service
;
package
pangea
.
hiagent
.
web
.
service
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.stereotype.Service
;
import
pangea.hiagent.web.repository.AgentDialogueRepository
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ConcurrentMap
;
import
java.util.concurrent.ConcurrentMap
;
...
@@ -10,6 +12,9 @@ import java.util.concurrent.ConcurrentMap;
...
@@ -10,6 +12,9 @@ import java.util.concurrent.ConcurrentMap;
@Service
@Service
public
class
ChatService
{
public
class
ChatService
{
@Autowired
private
AgentDialogueRepository
agentDialogueRepository
;
private
final
ConcurrentMap
<
String
,
String
>
chatList
=
new
ConcurrentHashMap
<>(
1024
);
private
final
ConcurrentMap
<
String
,
String
>
chatList
=
new
ConcurrentHashMap
<>(
1024
);
public
boolean
chatExists
(
String
userId
,
String
agentId
)
{
public
boolean
chatExists
(
String
userId
,
String
agentId
)
{
...
@@ -26,6 +31,7 @@ public class ChatService {
...
@@ -26,6 +31,7 @@ public class ChatService {
String
chatId
=
buildChatId
(
userId
,
agentId
);
String
chatId
=
buildChatId
(
userId
,
agentId
);
log
.
info
(
"remove chatId:{}"
,
chatId
);
log
.
info
(
"remove chatId:{}"
,
chatId
);
chatList
.
remove
(
chatId
);
chatList
.
remove
(
chatId
);
agentDialogueRepository
.
deleteDialogue
(
userId
,
agentId
);
}
}
private
String
buildChatId
(
String
userId
,
String
agentId
)
{
private
String
buildChatId
(
String
userId
,
String
agentId
)
{
...
...
backend/src/main/java/pangea/hiagent/web/service/InfoCollectorService.java
View file @
d2f8d7c9
...
@@ -52,15 +52,15 @@ public class InfoCollectorService {
...
@@ -52,15 +52,15 @@ public class InfoCollectorService {
for
(
int
i
=
0
;
i
<
jsonArray
.
size
();
i
++){
for
(
int
i
=
0
;
i
<
jsonArray
.
size
();
i
++){
JSONObject
object
=
jsonArray
.
getJSONObject
(
i
);
JSONObject
object
=
jsonArray
.
getJSONObject
(
i
);
if
(
object
.
getString
(
"field_name"
).
compareToIgnoreCase
(
"接访员工手机号"
)
==
0
){
if
(
object
.
getString
(
"field_name"
).
compareToIgnoreCase
(
"接访员工手机号"
)
==
0
){
String
code
=
object
.
getString
(
"
cod
e"
);
String
code
=
object
.
getString
(
"
field_nam
e"
);
saveValue
(
code
,
"15841169015"
);
saveValue
(
code
,
"15841169015"
);
}
}
if
(
object
.
getString
(
"field_name"
).
compareToIgnoreCase
(
"接访员工姓名"
)
==
0
){
if
(
object
.
getString
(
"field_name"
).
compareToIgnoreCase
(
"接访员工姓名"
)
==
0
){
String
code
=
object
.
getString
(
"
cod
e"
);
String
code
=
object
.
getString
(
"
field_nam
e"
);
saveValue
(
code
,
"杜艺"
);
saveValue
(
code
,
"杜艺"
);
}
}
if
(
object
.
getString
(
"field_name"
).
compareToIgnoreCase
(
"证件类型"
)
==
0
){
if
(
object
.
getString
(
"field_name"
).
compareToIgnoreCase
(
"证件类型"
)
==
0
){
String
code
=
object
.
getString
(
"
cod
e"
);
String
code
=
object
.
getString
(
"
field_nam
e"
);
saveValue
(
code
,
"居民身份证"
);
saveValue
(
code
,
"居民身份证"
);
}
}
}
}
...
@@ -73,7 +73,7 @@ public class InfoCollectorService {
...
@@ -73,7 +73,7 @@ public class InfoCollectorService {
public
Map
<
String
,
String
>
findLackInfo
(
String
pageId
)
{
public
Map
<
String
,
String
>
findLackInfo
(
String
pageId
)
{
Set
<
String
>
valueKeys
=
values
.
keySet
();
Set
<
String
>
valueKeys
=
values
.
keySet
();
log
.
info
(
"value keys {}"
,
valueKeys
);
log
.
info
(
"value keys {}"
,
valueKeys
);
Set
<
String
>
allKeys
=
infos
.
get
(
pageId
).
stream
().
map
(
t
->
((
JSONObject
)
t
).
getString
(
"
cod
e"
)).
collect
(
Collectors
.
toSet
());
Set
<
String
>
allKeys
=
infos
.
get
(
pageId
).
stream
().
map
(
t
->
((
JSONObject
)
t
).
getString
(
"
field_nam
e"
)).
collect
(
Collectors
.
toSet
());
log
.
info
(
"all keys {}"
,
allKeys
);
log
.
info
(
"all keys {}"
,
allKeys
);
allKeys
.
removeAll
(
valueKeys
);
allKeys
.
removeAll
(
valueKeys
);
log
.
info
(
"lack keys {}"
,
allKeys
);
log
.
info
(
"lack keys {}"
,
allKeys
);
...
@@ -86,7 +86,7 @@ public class InfoCollectorService {
...
@@ -86,7 +86,7 @@ public class InfoCollectorService {
infos
.
get
(
pageId
).
stream
().
forEach
(
t
->
infos
.
get
(
pageId
).
stream
().
forEach
(
t
->
{
{
JSONObject
info
=
(
JSONObject
)
t
;
JSONObject
info
=
(
JSONObject
)
t
;
String
code
=
info
.
getString
(
"
cod
e"
);
String
code
=
info
.
getString
(
"
field_nam
e"
);
if
(
allKeys
.
contains
(
code
))
{
if
(
allKeys
.
contains
(
code
))
{
lackInfos
.
put
(
code
,
info
.
getString
(
"field_name"
));
lackInfos
.
put
(
code
,
info
.
getString
(
"field_name"
));
}
}
...
...
backend/src/main/resources/application-dev.yml
View file @
d2f8d7c9
...
@@ -2,10 +2,10 @@
...
@@ -2,10 +2,10 @@
spring
:
spring
:
# 开发环境数据源配置
# 开发环境数据源配置
datasource
:
datasource
:
url
:
jdbc:
h2:file:./data/hiagent_dev_db;DB_CLOSE_ON_EXIT=FALSE
url
:
jdbc:
mysql://${DB_HOST:127.0.0.1}:3306/hiagent?allowMultiQueries=true&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai
driver-class-name
:
org.h2.Driver
driver-class-name
:
${DB_DRIVER:com.mysql.cj.jdbc.Driver}
username
:
sa
username
:
${DB_NAME:root}
password
:
sa
password
:
${DB_PASSWORD:password}
# 开发环境JPA配置
# 开发环境JPA配置
jpa
:
jpa
:
...
@@ -21,7 +21,7 @@ spring:
...
@@ -21,7 +21,7 @@ spring:
init
:
init
:
schema-locations
:
classpath:schema.sql
schema-locations
:
classpath:schema.sql
data-locations
:
classpath:data.sql
data-locations
:
classpath:data.sql
mode
:
always
# 总是执行创建表和数据脚本,实现重新初始化
mode
:
never
# 总是执行创建表和数据脚本,实现重新初始化
# 开启H2控制台
# 开启H2控制台
h2
:
h2
:
...
...
frontend/vite.config.ts
View file @
d2f8d7c9
/*
* @Date: 2025-12-29 14:42:27
* @LastEditors: wangduo3 wangduo3@hisense.com
* @LastEditTime: 2025-12-29 16:56:52
* @FilePath: /pangea-agent/frontend/vite.config.ts
*/
import
{
defineConfig
}
from
"vite"
;
import
{
defineConfig
}
from
"vite"
;
import
vue
from
"@vitejs/plugin-vue"
;
import
vue
from
"@vitejs/plugin-vue"
;
import
path
from
"path"
;
import
path
from
"path"
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment