Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
T
TestSpider
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Bugzilla
Bugzilla
Merge Requests
0
Merge Requests
0
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
尚立鹏
TestSpider
Commits
025a4e15
Commit
025a4e15
authored
Feb 10, 2023
by
shanglipeng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
代码完善
parent
f6bd2d52
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
828 additions
and
88 deletions
+828
-88
chrome_no_proxy.bat
files/chrome_no_proxy.bat
+1
-0
Main.java
src/main/java/com/greatchn/Main.java
+4
-1
BaseEtax.java
src/main/java/com/greatchn/etax/BaseEtax.java
+1
-1
ChromeKits.java
src/main/java/com/greatchn/kits/ChromeKits.java
+61
-0
ProcessKits.java
src/main/java/com/greatchn/kits/ProcessKits.java
+279
-0
RpaCore.java
src/main/java/com/greatchn/rpa/RpaCore.java
+341
-79
WinApi.java
src/main/java/com/greatchn/rpa/WinApi.java
+6
-0
RpaConfig.java
src/main/java/com/greatchn/rpa/config/RpaConfig.java
+6
-0
TaskExecutor.java
src/main/java/com/greatchn/yzh/TaskExecutor.java
+84
-4
rpa.yaml
src/main/resources/rpa.yaml
+17
-3
DriverTest.java
src/test/java/DriverTest.java
+28
-0
No files found.
files/chrome_no_proxy.bat
0 → 100644
View file @
025a4e15
"/Google/Chrome/Application/chrome.exe" --remote-debugging-port=9222 --user-data-dir="c:/selenium/ChromeProfile" --allow-pre-commit-input --disable-background-networking --disable-backgrounding-occluded-windows --disable-client-side-phishing-detection --disable-default-apps --disable-hang-monitor --disable-infobars --disable-popup-blocking --disable-prompt-on-repost --disable-sync --enable-blink-features=ShadowDOMV0 --enable-logging --ignore-certificate-errors --log-level=3 --no-service-autorun --password-store=basic --start-maximized --test-type --use-mock-keychain --flag-switches-begin --flag-switches-end
\ No newline at end of file
src/main/java/com/greatchn/Main.java
View file @
025a4e15
package
com
.
greatchn
;
package
com
.
greatchn
;
import
com.greatchn.kits.ChromeKits
;
import
com.greatchn.yzh.TaskExecutor
;
import
com.greatchn.yzh.TaskExecutor
;
/**
/**
...
@@ -9,7 +10,9 @@ import com.greatchn.yzh.TaskExecutor;
...
@@ -9,7 +10,9 @@ import com.greatchn.yzh.TaskExecutor;
* @since 1.0.0
* @since 1.0.0
*/
*/
public
class
Main
{
public
class
Main
{
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
ChromeKits
.
killBrowser
();
ChromeKits
.
utilBrowserStart
(
"./files/chrome_no_proxy.bat"
);
new
TaskExecutor
();
new
TaskExecutor
();
}
}
}
}
\ No newline at end of file
src/main/java/com/greatchn/etax/BaseEtax.java
View file @
025a4e15
...
@@ -76,7 +76,7 @@ public abstract class BaseEtax {
...
@@ -76,7 +76,7 @@ public abstract class BaseEtax {
return
this
.
config
;
return
this
.
config
;
}
}
p
rotected
RpaCore
rpa
()
{
p
ublic
RpaCore
rpa
()
{
return
this
.
rpa
;
return
this
.
rpa
;
}
}
...
...
src/main/java/com/greatchn/kits/ChromeKits.java
0 → 100644
View file @
025a4e15
package
com
.
greatchn
.
kits
;
import
org.apache.commons.lang3.StringUtils
;
import
java.io.BufferedReader
;
import
java.io.File
;
import
java.io.InputStreamReader
;
import
java.util.Arrays
;
import
java.util.Date
;
public
class
ChromeKits
{
public
static
void
killBrowser
(){
ProcessKits
.
killProcess
(
Arrays
.
asList
(
"firefox"
,
"geckodriver"
,
"crashreporter"
,
"chromedriver"
,
"chrome"
));
}
//创建浏览器
public
static
String
utilBrowserStart
(
String
batPath
)
throws
Exception
{
Runtime
rt
=
Runtime
.
getRuntime
();
try
{
Process
process
=
rt
.
exec
(
new
File
(
batPath
).
getAbsolutePath
());
// 获取启动返回信息
InputStreamReader
isr
=
new
InputStreamReader
(
process
.
getErrorStream
());
BufferedReader
br
=
new
BufferedReader
(
isr
);
long
startTime
=
new
Date
().
getTime
();
String
browserWs
=
""
;
while
(
true
)
{
if
(
new
Date
().
getTime
()
-
startTime
>=
60000
*
2
)
{
break
;
}
browserWs
=
br
.
readLine
();
if
(
browserWs
!=
null
&&
browserWs
.
startsWith
(
"DevTools"
))
{
browserWs
=
browserWs
.
substring
(
browserWs
.
indexOf
(
"ws:"
));
break
;
}
else
{
Thread
.
sleep
(
100
);
}
}
if
(
StringUtils
.
isEmpty
(
browserWs
))
{
throw
new
RuntimeException
(
"初始化chrome失败"
);
}
System
.
out
.
println
(
browserWs
);
return
browserWs
;
}
catch
(
Exception
e
)
{
throw
e
;
}
}
}
src/main/java/com/greatchn/kits/ProcessKits.java
0 → 100644
View file @
025a4e15
package
com
.
greatchn
.
kits
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.text.MessageFormat
;
import
java.util.List
;
public
class
ProcessKits
{
/**
* 判断指定进程是否存在
*
* @param processName
* @return
*/
public
static
Boolean
isProcessExist
(
String
processName
)
{
try
{
String
os
=
System
.
getProperty
(
"os.name"
);
if
(
os
.
toLowerCase
().
startsWith
(
"win"
))
{
return
isWindowsProcessExist
(
processName
);
}
if
(
os
.
toLowerCase
().
startsWith
(
"lin"
))
{
return
isLunuxProcessExist
(
processName
);
}
else
{
return
false
;
}
}
catch
(
Exception
e
)
{
return
false
;
}
}
public
static
boolean
isLunuxProcessExist
(
String
processName
)
{
BufferedReader
bufferedReader
=
null
;
try
{
Process
proc
=
Runtime
.
getRuntime
().
exec
(
"ps -e"
);
bufferedReader
=
new
BufferedReader
(
new
InputStreamReader
(
proc
.
getInputStream
()));
String
line
=
null
;
while
((
line
=
bufferedReader
.
readLine
())
!=
null
)
{
if
(
line
.
contains
(
processName
))
// 判断是否存在
{
return
true
;
}
}
return
false
;
}
catch
(
Exception
ex
)
{
ex
.
printStackTrace
();
return
false
;
}
finally
{
if
(
bufferedReader
!=
null
)
{
try
{
bufferedReader
.
close
();
}
catch
(
Exception
ex
)
{
}
}
}
}
public
static
boolean
isWindowsProcessExist
(
String
processName
)
{
BufferedReader
bufferedReader
=
null
;
try
{
String
cmd
=
MessageFormat
.
format
(
"{0}\\system32\\tasklist.exe"
,
System
.
getenv
(
"windir"
));
Process
proc
=
Runtime
.
getRuntime
().
exec
(
cmd
);
bufferedReader
=
new
BufferedReader
(
new
InputStreamReader
(
proc
.
getInputStream
()));
String
line
=
null
;
while
((
line
=
bufferedReader
.
readLine
())
!=
null
)
{
System
.
out
.
println
(
line
);
if
(
line
.
contains
(
processName
))
// 判断是否存在
{
return
true
;
}
}
return
false
;
}
catch
(
Exception
ex
)
{
ex
.
printStackTrace
();
return
false
;
}
finally
{
if
(
bufferedReader
!=
null
)
{
try
{
bufferedReader
.
close
();
}
catch
(
Exception
ex
)
{
}
}
}
}
public
static
Boolean
startProcess
(
List
<
String
>
exeFileFullPathNameList
)
{
try
{
String
os
=
System
.
getProperty
(
"os.name"
);
if
(
os
.
toLowerCase
().
startsWith
(
"win"
))
{
startWindowsProcess
(
exeFileFullPathNameList
);
}
if
(
os
.
toLowerCase
().
startsWith
(
"lin"
))
{
startLinuxProcess
(
exeFileFullPathNameList
);
}
else
{
return
false
;
}
return
true
;
}
catch
(
Exception
e
)
{
// TODO: handle exception
e
.
printStackTrace
();
return
false
;
}
}
private
static
void
startWindowsProcess
(
List
<
String
>
exeFileFullPathNameList
)
{
try
{
Runtime
runtime
=
Runtime
.
getRuntime
();
for
(
String
string
:
exeFileFullPathNameList
)
{
runtime
.
exec
(
string
);
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
private
static
void
startLinuxProcess
(
List
<
String
>
exeFileFullPathNameList
)
{
try
{
// 如果是 linux系统
for
(
String
processName
:
exeFileFullPathNameList
)
{
// String commandString = MessageFormat.format("ps -ef | grep {0} | grep -v grep | awk '''{'print $2'}''' | xargs kill -9", processName);
System
.
out
.
println
(
processName
);
// 当需要执行的linux命令带有管道符时(例如:ps -ef|grep java),用上面的方法是不行的,解决方式是将需要执行的命令作为参数传给shell
String
[]
cmds
=
{
"/bin/sh"
,
"-c"
,
processName
};
Runtime
.
getRuntime
().
exec
(
cmds
);
}
}
catch
(
Exception
e
)
{
// TODO: handle exception
e
.
printStackTrace
();
}
}
/**
* 根据进程名称集合结束进程
*
* @param processNameList
* 进程名称集合 例如firefox,chrome 不带后缀
* @return
*/
public
static
Boolean
killProcess
(
List
<
String
>
processNameList
)
{
try
{
String
os
=
System
.
getProperty
(
"os.name"
);
if
(
os
.
toLowerCase
().
startsWith
(
"win"
))
{
killWindowsProcess
(
processNameList
);
}
if
(
os
.
toLowerCase
().
startsWith
(
"lin"
))
{
killLinuxProcess
(
processNameList
);
}
else
{
return
false
;
}
return
true
;
}
catch
(
Exception
e
)
{
// TODO: handle exception
e
.
printStackTrace
();
return
false
;
}
}
/**
* 在windows环境下根据进程名称结束进程
*
* @param processNameList
* 进程名称集合
*/
private
static
void
killWindowsProcess
(
List
<
String
>
processNameList
)
{
try
{
// 如果是 windows系统
for
(
String
processName
:
processNameList
)
{
// String commandString=MessageFormat.format("taskkill /f /IM phantomjs.exe", arg1)
String
commandString
=
MessageFormat
.
format
(
"taskkill /f /IM {0}.exe"
,
processName
);
Runtime
.
getRuntime
().
exec
(
commandString
);
}
}
catch
(
Exception
e
)
{
// TODO: handle exception
e
.
printStackTrace
();
}
}
/**
* 在Linux环境下根据进程名称结束进程
*
* @param processNameList
* 进程名称集合
*/
private
static
void
killLinuxProcess
(
List
<
String
>
processNameList
)
{
try
{
// 如果是 linux系统
for
(
String
processName
:
processNameList
)
{
String
commandString
=
MessageFormat
.
format
(
"ps -ef | grep {0} | grep -v grep | awk '''{'print $2'}''' | xargs kill -9"
,
processName
);
System
.
out
.
println
(
commandString
);
// 当需要执行的linux命令带有管道符时(例如:ps -ef|grep java),用上面的方法是不行的,解决方式是将需要执行的命令作为参数传给shell
String
[]
cmds
=
{
"/bin/sh"
,
"-c"
,
commandString
};
Runtime
.
getRuntime
().
exec
(
cmds
);
}
}
catch
(
Exception
e
)
{
// TODO: handle exception
e
.
printStackTrace
();
}
}
}
src/main/java/com/greatchn/rpa/RpaCore.java
View file @
025a4e15
This diff is collapsed.
Click to expand it.
src/main/java/com/greatchn/rpa/WinApi.java
View file @
025a4e15
...
@@ -4,6 +4,7 @@ import com.greatchn.rpa.beans.Button;
...
@@ -4,6 +4,7 @@ import com.greatchn.rpa.beans.Button;
import
com.greatchn.rpa.beans.Point
;
import
com.greatchn.rpa.beans.Point
;
import
java.awt.*
;
import
java.awt.*
;
import
java.awt.event.KeyEvent
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeUnit
;
...
@@ -144,6 +145,11 @@ public final class WinApi {
...
@@ -144,6 +145,11 @@ public final class WinApi {
}
}
}
}
public
static
void
enter
(){
ROBOT
.
keyPress
(
KeyEvent
.
VK_ENTER
);
ROBOT
.
keyRelease
(
KeyEvent
.
VK_ENTER
);
}
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
{
mouseMove
(
0
,
0
);
mouseMove
(
0
,
0
);
mouseMove
(
1000
,
1000
,
1000
);
mouseMove
(
1000
,
1000
,
1000
);
...
...
src/main/java/com/greatchn/rpa/config/RpaConfig.java
View file @
025a4e15
...
@@ -22,6 +22,12 @@ public class RpaConfig {
...
@@ -22,6 +22,12 @@ public class RpaConfig {
private
Browser
browser
;
private
Browser
browser
;
private
Rpa
rpa
;
private
Rpa
rpa
;
private
Double
scale
;
private
Double
scale
;
//新增参数
private
boolean
useSeleniumDrag
;
private
boolean
networkProxy
;
private
boolean
remoteDebugging
;
private
int
remoteDebuggingPort
;
private
String
remoteDebuggingIP
;
/**
/**
* 使用默认配置文件加载配置
* 使用默认配置文件加载配置
...
...
src/main/java/com/greatchn/yzh/TaskExecutor.java
View file @
025a4e15
package
com
.
greatchn
.
yzh
;
package
com
.
greatchn
.
yzh
;
import
cn.hutool.core.date.DateUtil
;
import
com.greatchn.etax.monitor.Monitor
;
import
com.greatchn.etax.monitor.Monitor
;
import
com.greatchn.etax.tianjin.Tianjin
;
import
com.greatchn.etax.tianjin.Tianjin
;
import
com.greatchn.kits.EnvironmentToolkit
;
import
com.greatchn.kits.EnvironmentToolkit
;
import
com.greatchn.kits.HashKits
;
import
com.greatchn.kits.HashKits
;
import
com.greatchn.rpa.WinApi
;
import
com.greatchn.rpa.config.RpaConfig
;
import
com.greatchn.rpa.config.RpaConfig
;
import
com.greatchn.yzh.db.Db
;
import
com.greatchn.yzh.db.Db
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.openqa.selenium.By
;
import
org.openqa.selenium.OutputType
;
import
org.openqa.selenium.WebElement
;
import
java.io.File
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.charset.StandardCharsets
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.concurrent.ScheduledThreadPoolExecutor
;
import
java.util.concurrent.ScheduledThreadPoolExecutor
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeUnit
;
import
java.util.stream.Collectors
;
/**
/**
* 云账户 RPA 任务处理器
* 云账户 RPA 任务处理器
...
@@ -25,21 +36,90 @@ public final class TaskExecutor {
...
@@ -25,21 +36,90 @@ public final class TaskExecutor {
private
final
Tianjin
tianjin
;
private
final
Tianjin
tianjin
;
private
final
Monitor
monitor
;
private
final
Monitor
monitor
=
null
;
private
final
String
instanceID
;
private
final
String
instanceID
;
private
final
String
ip
;
private
final
String
ip
;
public
TaskExecutor
()
{
public
TaskExecutor
()
throws
InterruptedException
{
instanceID
=
"%s_java_rpa"
.
formatted
(
HashKits
.
sha256
(
EnvironmentToolkit
.
getMac
().
getBytes
(
StandardCharsets
.
UTF_8
)));
instanceID
=
"%s_java_rpa"
.
formatted
(
HashKits
.
sha256
(
EnvironmentToolkit
.
getMac
().
getBytes
(
StandardCharsets
.
UTF_8
)));
ip
=
EnvironmentToolkit
.
getLocalIp
();
ip
=
EnvironmentToolkit
.
getLocalIp
();
db
=
new
Db
();
db
=
new
Db
();
tianjin
=
new
Tianjin
(
RpaConfig
.
build
(
"rpa.yaml"
));
tianjin
=
new
Tianjin
(
RpaConfig
.
build
(
"rpa.yaml"
));
monitor
=
new
Monitor
();
// monitor = new Monitor();
String
taxFileNo
=
"91120116MA05TT0A0D"
;
tianjin
.
login
(
taxFileNo
,
"13516135467"
,
"Badboy1993"
);
tianjin
.
login
(
"91120223MA079XXY07"
,
"131026199607185115"
,
"ds111111"
);
//我要办税
WebElement
wybs
=
tianjin
.
rpa
().
findElement
(
By
.
xpath
(
".//a[text()='我要办税']"
),
10
);
tianjin
.
rpa
().
click
(
wybs
);
//frame
WebElement
iframe
=
tianjin
.
rpa
().
findElement
(
By
.
cssSelector
(
"#profile > iframe"
),
10
);
//税务数字账户
tianjin
.
rpa
().
switchToFrame
(
iframe
);
WebElement
swsszh
=
tianjin
.
rpa
().
findElement
(
By
.
xpath
(
".//li[@title='税务数字账户']"
),
10
);
tianjin
.
rpa
().
click
(
swsszh
);
tianjin
.
rpa
().
switchToParent
();
//tianjin.rpa().listen("/menuAuth/getMenuAuthSwitch.do",10);
tianjin
.
rpa
().
refresh
();
System
.
out
.
println
(
"已刷新"
);
//税务数字账户2
WebElement
swsszh2
=
tianjin
.
rpa
().
findElement
(
By
.
xpath
(
".//div[@class='leftPanel-li-div']//span[text()='税务数字账户']"
),
10
);
tianjin
.
rpa
().
click
(
swsszh2
);
System
.
out
.
println
(
"税务数字账户2点击完毕"
);
Thread
.
sleep
(
10000L
);
tianjin
.
rpa
().
sendEnterCmd
(
10000
);
while
(
true
)
{
//new page
Thread
.
sleep
(
1000
);
Set
<
String
>
windowHandles
=
tianjin
.
rpa
().
getWindowHandles
();
System
.
out
.
println
(
"windowHandles:"
+
windowHandles
.
size
());
if
(
windowHandles
.
size
()>
1
)
{
List
<
String
>
collect
=
windowHandles
.
stream
().
collect
(
Collectors
.
toList
());
tianjin
.
rpa
().
switchWindow
(
collect
.
get
(
1
));
break
;
}
}
tianjin
.
rpa
().
visit
(
"https://dppt.tianjin.chinatax.gov.cn:8443/invoice-query/invoice-query?ruuid="
+
System
.
currentTimeMillis
());
Thread
.
sleep
(
10000L
);
tianjin
.
rpa
().
sendEnterCmd
(
10000
);
//发票查询统计
// WebElement fpcxtj = tianjin.rpa().findElement(By.xpath(".//div[@class='app_name__bold'][text()='发票查询统计']"),10);
// tianjin.rpa().click(fpcxtj);
//全量发票查询
// WebElement qlfpcx = tianjin.rpa().findElement(By.xpath(".//div[@class='g-card-menu-item__title'][text()='全量发票查询']"));
// tianjin.rpa().click(qlfpcx);
// tianjin.rpa().visit("https://dppt.tianjin.chinatax.gov.cn:8443/invoice-query/invoice-query?"+System.currentTimeMillis());
tianjin
.
rpa
().
newHar
();
WebElement
queryButton
=
tianjin
.
rpa
().
findElement
(
By
.
xpath
(
".//span[text()='查询']"
),
60
);
tianjin
.
rpa
().
click
(
queryButton
);
tianjin
.
rpa
().
listen
(
"/qlfpcx/v1/queryFpjeseHj"
,
10
);
File
srcFile
=
tianjin
.
rpa
().
driver
().
getScreenshotAs
(
OutputType
.
FILE
);
srcFile
.
renameTo
(
new
File
(
"./files/全电_%s_%s.jpg"
.
formatted
(
taxFileNo
,
DateUtil
.
format
(
new
Date
(),
"yyyy_MM_dd HH_mm_ss"
))));
System
.
out
.
println
(
"finish"
);
// tianjin.queryDutyPaidProof("91120223MA079XXY07", "131026199607185115", "ds111111","510211201000000362315","2019-01-01", "2019-12-31");
// tianjin.queryDutyPaidProof("91120223MA079XXY07", "131026199607185115", "ds111111","510211201000000362315","2019-01-01", "2019-12-31");
// 心跳
// 心跳
{
{
...
...
src/main/resources/rpa.yaml
View file @
025a4e15
...
@@ -3,13 +3,27 @@ selenium:
...
@@ -3,13 +3,27 @@ selenium:
browser
:
browser
:
chrome
:
/Google/Chrome/Application/chrome.exe
chrome
:
/Google/Chrome/Application/chrome.exe
rpa
:
rpa
:
#Mobo代理
proxy
:
proxy
:
enable
:
tru
e
enable
:
fals
e
port
:
30001
port
:
30001
cookies
:
cookies
:
clean
:
true
clean
:
true
fullScreen
:
false
fullScreen
:
false
autoScroll
:
true
autoScroll
:
true
autoCreate
:
true
autoCreate
:
true
simulate
:
true
simulate
:
false
#新增参数
useSeleniumDrag
:
true
#chrome的network,不可以与Mobo代理同时打开
networkProxy
:
true
#是否使用selenium来自动启动浏览器
remoteDebugging
:
true
remoteDebuggingPort
:
9222
remoteDebuggingIP
:
"
127.0.0.1"
scale
:
1.00
scale
:
1.00
src/test/java/DriverTest.java
0 → 100644
View file @
025a4e15
import
com.greatchn.rpa.RpaCore
;
import
com.greatchn.rpa.config.RpaConfig
;
import
com.greatchn.yzh.TaskExecutor
;
import
org.openqa.selenium.By
;
import
org.openqa.selenium.WebElement
;
public
class
DriverTest
{
public
static
void
main
(
String
[]
args
)
throws
InterruptedException
{
var
config
=
RpaConfig
.
build
();
RpaCore
rpa
=
new
RpaCore
(
config
);
rpa
.
visit
(
"chrome://version/"
);
//network
//rpa.enableNetWork();
rpa
.
visit
(
"https://www.baidu.com"
);
System
.
out
.
println
(
rpa
.
listenNetWorkCenter
(
"sugrec"
,
10000L
));
//drag
rpa
.
visit
(
"https://tpass.tianjin.chinatax.gov.cn:8443/#/login?redirect_uri=https%3A%2F%2Fetax.tianjin.chinatax.gov.cn%2Foutsider%2Fsso%2FmainPage.do&client_id=x3ef652ax3294xz6beefnf5zadbf66cc&response_type=code&state=test"
);
var
dragHandler
=
rpa
.
findElement
(
By
.
cssSelector
(
".handler.animate"
),
1
);
WebElement
continer
=
rpa
.
findElement
(
dragHandler
,
By
.
xpath
(
"./.."
));
System
.
out
.
println
(
continer
.
getText
());
rpa
.
drag
(
dragHandler
,
continer
);
}
}
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