mirror of
https://github.com/XZB-1248/Spark
synced 2025-10-23 15:43:22 +08:00
add: i18n support
This commit is contained in:
@@ -1,3 +1,11 @@
|
|||||||
|
## v0.0.4
|
||||||
|
|
||||||
|
* Add: i18n support
|
||||||
|
|
||||||
|
* 新增:支持中英文国际化
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## v0.0.3
|
## v0.0.3
|
||||||
|
|
||||||
* Add: network IO speed monitoring.
|
* Add: network IO speed monitoring.
|
||||||
|
@@ -16,8 +16,7 @@
|
|||||||
|
|
||||||
现在暂时只支持本地安装,暂时还没有Docker等安装方式。
|
现在暂时只支持本地安装,暂时还没有Docker等安装方式。
|
||||||
|
|
||||||
<details>
|
### 本地安装
|
||||||
<summary>本地安装</summary>
|
|
||||||
|
|
||||||
* 从 [Releases](https://github.com/XZB-1248/Spark/releases) 页面下载对应系统的可执行文件。
|
* 从 [Releases](https://github.com/XZB-1248/Spark/releases) 页面下载对应系统的可执行文件。
|
||||||
* 修改配置文件,特别是salt,需要修改成你自己的。
|
* 修改配置文件,特别是salt,需要修改成你自己的。
|
||||||
@@ -36,8 +35,6 @@
|
|||||||
* 在管理页面中生成客户端,并部署到设备上。
|
* 在管理页面中生成客户端,并部署到设备上。
|
||||||
* 现在就可以控制这个设备了。
|
* 现在就可以控制这个设备了。
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **特性**
|
## **特性**
|
||||||
|
@@ -11,9 +11,7 @@ that allow you to control all your devices via browser anywhere.
|
|||||||
|
|
||||||
Only local installation are available yet.
|
Only local installation are available yet.
|
||||||
|
|
||||||
<details>
|
### Local installation
|
||||||
<summary>Local installation:</summary>
|
|
||||||
|
|
||||||
* Get prebuilt executable file from [Releases](https://github.com/XZB-1248/Spark/releases) page.
|
* Get prebuilt executable file from [Releases](https://github.com/XZB-1248/Spark/releases) page.
|
||||||
* Modify configuration file and set your own salt.
|
* Modify configuration file and set your own salt.
|
||||||
|
|
||||||
@@ -27,12 +25,10 @@ Only local installation are available yet.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
* Run it and browser the address:port you've just set.
|
* Run it and browse the address:port you've just set.
|
||||||
* Generate client online and execute it on your device.
|
* Generate client online and execute it on your device.
|
||||||
* Now you can control your device.
|
* Now you can control your device.
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **Features**
|
## **Features**
|
||||||
|
@@ -20,7 +20,7 @@ type Cfg struct {
|
|||||||
// none
|
// none
|
||||||
var CfgBuffer = "\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19"
|
var CfgBuffer = "\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19"
|
||||||
|
|
||||||
// COMMIT means this commit hash, for auto upgrade.
|
// COMMIT means this commit hash, help to identify version and self upgrade.
|
||||||
var COMMIT = ``
|
var COMMIT = ``
|
||||||
var Config Cfg
|
var Config Cfg
|
||||||
|
|
||||||
|
@@ -12,9 +12,6 @@ import (
|
|||||||
"Spark/utils"
|
"Spark/utils"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
ws "github.com/gorilla/websocket"
|
|
||||||
"github.com/imroc/req/v3"
|
|
||||||
"github.com/kataras/golog"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@@ -22,6 +19,10 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
ws "github.com/gorilla/websocket"
|
||||||
|
"github.com/imroc/req/v3"
|
||||||
|
"github.com/kataras/golog"
|
||||||
)
|
)
|
||||||
|
|
||||||
// simplified type of map
|
// simplified type of map
|
||||||
@@ -78,6 +79,9 @@ func connectWS() (*common.Conn, error) {
|
|||||||
return nil, errNoSecretHeader
|
return nil, errNoSecretHeader
|
||||||
}
|
}
|
||||||
secret, err := hex.DecodeString(header[0])
|
secret, err := hex.DecodeString(header[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &common.Conn{Conn: wsConn, Secret: secret}, nil
|
return &common.Conn{Conn: wsConn, Secret: secret}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,13 +250,10 @@ func handleAct(pack modules.Packet, wsConn *common.Conn) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Act: `initTerminal`, Code: 1, Msg: err.Error()}, pack, wsConn)
|
common.SendCb(modules.Packet{Act: `initTerminal`, Code: 1, Msg: err.Error()}, pack, wsConn)
|
||||||
}
|
}
|
||||||
break
|
|
||||||
case `inputTerminal`:
|
case `inputTerminal`:
|
||||||
terminal.InputTerminal(pack)
|
terminal.InputTerminal(pack)
|
||||||
break
|
|
||||||
case `killTerminal`:
|
case `killTerminal`:
|
||||||
terminal.KillTerminal(pack)
|
terminal.KillTerminal(pack)
|
||||||
break
|
|
||||||
case `listFiles`:
|
case `listFiles`:
|
||||||
path := `/`
|
path := `/`
|
||||||
if val, ok := pack.Data[`path`]; ok {
|
if val, ok := pack.Data[`path`]; ok {
|
||||||
@@ -293,11 +294,11 @@ func handleAct(pack modules.Packet, wsConn *common.Conn) {
|
|||||||
{
|
{
|
||||||
tempVal, ok := pack.Data[`file`]
|
tempVal, ok := pack.Data[`file`]
|
||||||
if !ok {
|
if !ok {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `未知错误`}, pack, wsConn)
|
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|unknownError}`}, pack, wsConn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if path, ok = tempVal.(string); !ok {
|
if path, ok = tempVal.(string); !ok {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `未知错误`}, pack, wsConn)
|
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|unknownError}`}, pack, wsConn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tempVal, ok = pack.Data[`start`]
|
tempVal, ok = pack.Data[`start`]
|
||||||
@@ -316,7 +317,7 @@ func handleAct(pack modules.Packet, wsConn *common.Conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if end > 0 && end < start {
|
if end > 0 && end < start {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `文件范围错误`}, pack, wsConn)
|
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|invalidFileRange}`}, pack, wsConn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,12 +335,12 @@ func handleAct(pack modules.Packet, wsConn *common.Conn) {
|
|||||||
case `killProcess`:
|
case `killProcess`:
|
||||||
pidStr, ok := pack.Data[`pid`]
|
pidStr, ok := pack.Data[`pid`]
|
||||||
if !ok {
|
if !ok {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `未知错误`}, pack, wsConn)
|
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|unknownError}`}, pack, wsConn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pid, err := strconv.ParseInt(pidStr.(string), 10, 32)
|
pid, err := strconv.ParseInt(pidStr.(string), 10, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `未知错误`}, pack, wsConn)
|
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|unknownError}`}, pack, wsConn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = process.KillProcess(int32(pid))
|
err = process.KillProcess(int32(pid))
|
||||||
@@ -351,7 +352,6 @@ func handleAct(pack modules.Packet, wsConn *common.Conn) {
|
|||||||
default:
|
default:
|
||||||
common.SendCb(modules.Packet{Code: 0}, pack, wsConn)
|
common.SendCb(modules.Packet{Code: 0}, pack, wsConn)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func heartbeat(wsConn *common.Conn) error {
|
func heartbeat(wsConn *common.Conn) error {
|
||||||
|
@@ -3,11 +3,12 @@ package file
|
|||||||
import (
|
import (
|
||||||
"Spark/client/config"
|
"Spark/client/config"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/imroc/req/v3"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/imroc/req/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type file struct {
|
type file struct {
|
||||||
@@ -58,7 +59,7 @@ func UploadFile(path, trigger string, start, end int64) error {
|
|||||||
`FileSize`: strconv.FormatInt(size, 10),
|
`FileSize`: strconv.FormatInt(size, 10),
|
||||||
}
|
}
|
||||||
if size < end {
|
if size < end {
|
||||||
return errors.New(`文件大小有误`)
|
return errors.New(`Invalid file size.`)
|
||||||
}
|
}
|
||||||
if end == 0 {
|
if end == 0 {
|
||||||
uploadReq.RawRequest.ContentLength = size - start
|
uploadReq.RawRequest.ContentLength = size - start
|
||||||
|
@@ -7,14 +7,15 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"golang.org/x/text/encoding/simplifiedchinese"
|
|
||||||
"golang.org/x/text/transform"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/text/encoding/simplifiedchinese"
|
||||||
|
"golang.org/x/text/transform"
|
||||||
)
|
)
|
||||||
|
|
||||||
type terminal struct {
|
type terminal struct {
|
||||||
@@ -124,12 +125,12 @@ func InputTerminal(pack modules.Packet) error {
|
|||||||
}
|
}
|
||||||
val, ok = terminals.Get(termUUID)
|
val, ok = terminals.Get(termUUID)
|
||||||
if !ok {
|
if !ok {
|
||||||
common.SendCb(modules.Packet{Act: `quitTerminal`, Msg: `终端已退出`}, pack, common.WSConn)
|
common.SendCb(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack, common.WSConn)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
terminal, ok := val.(*terminal)
|
terminal, ok := val.(*terminal)
|
||||||
if !ok {
|
if !ok {
|
||||||
common.SendCb(modules.Packet{Act: `quitTerminal`, Msg: `终端已退出`}, pack, common.WSConn)
|
common.SendCb(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack, common.WSConn)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,13 +158,13 @@ func KillTerminal(pack modules.Packet) error {
|
|||||||
}
|
}
|
||||||
val, ok = terminals.Get(termUUID)
|
val, ok = terminals.Get(termUUID)
|
||||||
if !ok {
|
if !ok {
|
||||||
common.SendCb(modules.Packet{Act: `quitTerminal`, Msg: `终端已退出`}, pack, common.WSConn)
|
common.SendCb(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack, common.WSConn)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
terminal, ok := val.(*terminal)
|
terminal, ok := val.(*terminal)
|
||||||
if !ok {
|
if !ok {
|
||||||
terminals.Remove(termUUID)
|
terminals.Remove(termUUID)
|
||||||
common.SendCb(modules.Packet{Act: `quitTerminal`, Msg: `终端已退出`}, pack, common.WSConn)
|
common.SendCb(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack, common.WSConn)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
doKillTerminal(terminal)
|
doKillTerminal(terminal)
|
||||||
|
2
go.mod
2
go.mod
@@ -40,6 +40,6 @@ require (
|
|||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
|
||||||
golang.org/x/net v0.0.0-20220111093109-d55c255bac03 // indirect
|
golang.org/x/net v0.0.0-20220111093109-d55c255bac03 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 // indirect
|
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7
|
||||||
gopkg.in/yaml.v2 v2.2.8 // indirect
|
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||||
)
|
)
|
||||||
|
@@ -16,8 +16,8 @@ type EventCallback func(modules.Packet, *melody.Session)
|
|||||||
|
|
||||||
var eventTable = cmap.New()
|
var eventTable = cmap.New()
|
||||||
|
|
||||||
// CallEvent 负责判断packet中的Callback字段,如果存在该字段,
|
// CallEvent tries to call the callback with the given uuid
|
||||||
// 就会调用event中的函数,并在调用完成之后通过chan通知addOnceEvent调用方
|
// after that, it will notify the caller via the channel
|
||||||
func CallEvent(pack modules.Packet, session *melody.Session) {
|
func CallEvent(pack modules.Packet, session *melody.Session) {
|
||||||
if len(pack.Event) == 0 {
|
if len(pack.Event) == 0 {
|
||||||
return
|
return
|
||||||
@@ -40,8 +40,9 @@ func CallEvent(pack modules.Packet, session *melody.Session) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddEventOnce 会添加一个一次性的回调命令,client可以对事件成功与否进行回复
|
// AddEventOnce adds a new event only once and client
|
||||||
// trigger一般是uuid,以此尽可能保证事件的独一无二
|
// can call back the event with the given event trigger.
|
||||||
|
// Event trigger should be uuid to make every event unique.
|
||||||
func AddEventOnce(fn EventCallback, connUUID, trigger string, timeout time.Duration) bool {
|
func AddEventOnce(fn EventCallback, connUUID, trigger string, timeout time.Duration) bool {
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
ev := &event{
|
ev := &event{
|
||||||
@@ -59,8 +60,8 @@ func AddEventOnce(fn EventCallback, connUUID, trigger string, timeout time.Durat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddEvent 会添加一个持续的回调命令,client可以对事件成功与否进行回复
|
// AddEvent adds a new event and client can call back
|
||||||
// trigger一般是uuid,以此尽可能保证事件的独一无二
|
// the event with the given event trigger.
|
||||||
func AddEvent(fn EventCallback, connUUID, trigger string) {
|
func AddEvent(fn EventCallback, connUUID, trigger string) {
|
||||||
ev := &event{
|
ev := &event{
|
||||||
connection: connUUID,
|
connection: connUUID,
|
||||||
@@ -70,7 +71,7 @@ func AddEvent(fn EventCallback, connUUID, trigger string) {
|
|||||||
eventTable.Set(trigger, ev)
|
eventTable.Set(trigger, ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveEvent 会删除特定的回调命令
|
// RemoveEvent deletes the event with the given event trigger.
|
||||||
func RemoveEvent(trigger string) {
|
func RemoveEvent(trigger string) {
|
||||||
eventTable.Remove(trigger)
|
eventTable.Remove(trigger)
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,7 @@ func removeDeviceFile(ctx *gin.Context) {
|
|||||||
Device string `json:"device" yaml:"device" form:"device"`
|
Device string `json:"device" yaml:"device" form:"device"`
|
||||||
}
|
}
|
||||||
if ctx.ShouldBind(&form) != nil || (len(form.Conn) == 0 && len(form.Device) == 0) {
|
if ctx.ShouldBind(&form) != nil || (len(form.Conn) == 0 && len(form.Device) == 0) {
|
||||||
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `参数不完整`})
|
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
target := ``
|
target := ``
|
||||||
@@ -34,13 +34,13 @@ func removeDeviceFile(ctx *gin.Context) {
|
|||||||
ok := false
|
ok := false
|
||||||
target, ok = common.CheckDevice(form.Device)
|
target, ok = common.CheckDevice(form.Device)
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `未找到该设备`})
|
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|deviceNotExists}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
target = form.Conn
|
target = form.Conn
|
||||||
if !common.Devices.Has(target) {
|
if !common.Devices.Has(target) {
|
||||||
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `未找到该设备`})
|
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|deviceNotExists}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ func removeDeviceFile(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
}, target, trigger, 5*time.Second)
|
}, target, trigger, 5*time.Second)
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.JSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `响应超时`})
|
ctx.JSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ func listDeviceFiles(ctx *gin.Context) {
|
|||||||
Device string `json:"device" yaml:"device" form:"device"`
|
Device string `json:"device" yaml:"device" form:"device"`
|
||||||
}
|
}
|
||||||
if ctx.ShouldBind(&form) != nil || (len(form.Conn) == 0 && len(form.Device) == 0) {
|
if ctx.ShouldBind(&form) != nil || (len(form.Conn) == 0 && len(form.Device) == 0) {
|
||||||
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `参数不完整`})
|
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
connUUID := ``
|
connUUID := ``
|
||||||
@@ -74,13 +74,13 @@ func listDeviceFiles(ctx *gin.Context) {
|
|||||||
ok := false
|
ok := false
|
||||||
connUUID, ok = common.CheckDevice(form.Device)
|
connUUID, ok = common.CheckDevice(form.Device)
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `未找到该设备`})
|
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|deviceNotExists}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
connUUID = form.Conn
|
connUUID = form.Conn
|
||||||
if !common.Devices.Has(connUUID) {
|
if !common.Devices.Has(connUUID) {
|
||||||
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `未找到该设备`})
|
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|deviceNotExists}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ func listDeviceFiles(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
}, connUUID, trigger, 5*time.Second)
|
}, connUUID, trigger, 5*time.Second)
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.JSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `响应超时`})
|
ctx.JSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ func getDeviceFile(ctx *gin.Context) {
|
|||||||
Device string `json:"device" yaml:"device" form:"device"`
|
Device string `json:"device" yaml:"device" form:"device"`
|
||||||
}
|
}
|
||||||
if ctx.ShouldBind(&form) != nil || (len(form.Conn) == 0 && len(form.Device) == 0) {
|
if ctx.ShouldBind(&form) != nil || (len(form.Conn) == 0 && len(form.Device) == 0) {
|
||||||
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `参数不完整`})
|
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
target := ``
|
target := ``
|
||||||
@@ -115,13 +115,13 @@ func getDeviceFile(ctx *gin.Context) {
|
|||||||
ok := false
|
ok := false
|
||||||
target, ok = common.CheckDevice(form.Device)
|
target, ok = common.CheckDevice(form.Device)
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `未找到该设备`})
|
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|deviceNotExists}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
target = form.Conn
|
target = form.Conn
|
||||||
if !common.Devices.Has(target) {
|
if !common.Devices.Has(target) {
|
||||||
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `未找到该设备`})
|
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|deviceNotExists}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,13 +179,13 @@ func getDeviceFile(ctx *gin.Context) {
|
|||||||
val, ok := p.Data[`request`]
|
val, ok := p.Data[`request`]
|
||||||
if !ok {
|
if !ok {
|
||||||
wait <- false
|
wait <- false
|
||||||
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `文件上传失败`})
|
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `${i18n|fileUploadFailed}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req, ok := val.(*http.Request)
|
req, ok := val.(*http.Request)
|
||||||
if !ok || req == nil || req.Body == nil {
|
if !ok || req == nil || req.Body == nil {
|
||||||
wait <- false
|
wait <- false
|
||||||
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `文件上传失败`})
|
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `${i18n|fileUploadFailed}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +234,7 @@ func getDeviceFile(ctx *gin.Context) {
|
|||||||
case <-time.After(5 * time.Second):
|
case <-time.After(5 * time.Second):
|
||||||
if !called {
|
if !called {
|
||||||
common.RemoveEvent(trigger)
|
common.RemoveEvent(trigger)
|
||||||
ctx.JSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `响应超时`})
|
ctx.JSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
|
||||||
} else {
|
} else {
|
||||||
<-wait
|
<-wait
|
||||||
}
|
}
|
||||||
@@ -251,13 +251,13 @@ func putDeviceFile(ctx *gin.Context) {
|
|||||||
trigger := ctx.GetHeader(`Trigger`)
|
trigger := ctx.GetHeader(`Trigger`)
|
||||||
if len(trigger) == 0 {
|
if len(trigger) == 0 {
|
||||||
original.Close()
|
original.Close()
|
||||||
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `参数不完整`})
|
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(errMsg) > 0 {
|
if len(errMsg) > 0 {
|
||||||
common.CallEvent(modules.Packet{
|
common.CallEvent(modules.Packet{
|
||||||
Code: 1,
|
Code: 1,
|
||||||
Msg: fmt.Sprintf(`文件上传失败:%v`, errMsg),
|
Msg: fmt.Sprintf(`${i18n|fileUploadFailed}: %v`, errMsg),
|
||||||
Event: trigger,
|
Event: trigger,
|
||||||
}, nil)
|
}, nil)
|
||||||
original.Close()
|
original.Close()
|
||||||
|
@@ -58,12 +58,12 @@ func checkClient(ctx *gin.Context) {
|
|||||||
Secure string `json:"secure" yaml:"secure" form:"secure"`
|
Secure string `json:"secure" yaml:"secure" form:"secure"`
|
||||||
}
|
}
|
||||||
if err := ctx.ShouldBind(&form); err != nil {
|
if err := ctx.ShouldBind(&form); err != nil {
|
||||||
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `参数不完整`})
|
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err := common.BuiltFS.Open(fmt.Sprintf(`/%v_%v`, form.OS, form.Arch))
|
_, err := common.BuiltFS.Open(fmt.Sprintf(`/%v_%v`, form.OS, form.Arch))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.JSON(http.StatusNotFound, modules.Packet{Code: 1, Msg: `该系统或架构的客户端尚未编译`})
|
ctx.JSON(http.StatusNotFound, modules.Packet{Code: 1, Msg: `${i18n|osOrArchNotPrebuilt}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = genConfig(clientCfg{
|
_, err = genConfig(clientCfg{
|
||||||
@@ -76,10 +76,10 @@ func checkClient(ctx *gin.Context) {
|
|||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == errTooLargeEntity {
|
if err == errTooLargeEntity {
|
||||||
ctx.JSON(http.StatusRequestEntityTooLarge, modules.Packet{Code: 1, Msg: `配置信息过长`})
|
ctx.JSON(http.StatusRequestEntityTooLarge, modules.Packet{Code: 1, Msg: `${i18n|tooLargeConfig}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `配置文件生成失败`})
|
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `${i18n|configGenerateFailed}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.JSON(http.StatusOK, modules.Packet{Code: 0})
|
ctx.JSON(http.StatusOK, modules.Packet{Code: 0})
|
||||||
@@ -95,18 +95,18 @@ func generateClient(ctx *gin.Context) {
|
|||||||
Secure string `json:"secure" yaml:"secure" form:"secure"`
|
Secure string `json:"secure" yaml:"secure" form:"secure"`
|
||||||
}
|
}
|
||||||
if err := ctx.ShouldBind(&form); err != nil {
|
if err := ctx.ShouldBind(&form); err != nil {
|
||||||
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `参数不完整`})
|
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tpl, err := common.BuiltFS.Open(fmt.Sprintf(`/%v_%v`, form.OS, form.Arch))
|
tpl, err := common.BuiltFS.Open(fmt.Sprintf(`/%v_%v`, form.OS, form.Arch))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.JSON(http.StatusNotFound, modules.Packet{Code: 1, Msg: `该系统或架构的客户端尚未编译`})
|
ctx.JSON(http.StatusNotFound, modules.Packet{Code: 1, Msg: `${i18n|osOrArchNotPrebuilt}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
clientUUID := utils.GetUUID()
|
clientUUID := utils.GetUUID()
|
||||||
clientKey, err := common.EncAES(clientUUID, config.Config.StdSalt)
|
clientKey, err := common.EncAES(clientUUID, config.Config.StdSalt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `配置文件生成失败`})
|
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `${i18n|configGenerateFailed}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cfgBytes, err := genConfig(clientCfg{
|
cfgBytes, err := genConfig(clientCfg{
|
||||||
@@ -119,10 +119,10 @@ func generateClient(ctx *gin.Context) {
|
|||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == errTooLargeEntity {
|
if err == errTooLargeEntity {
|
||||||
ctx.JSON(http.StatusRequestEntityTooLarge, modules.Packet{Code: 1, Msg: `配置信息过长`})
|
ctx.JSON(http.StatusRequestEntityTooLarge, modules.Packet{Code: 1, Msg: `${i18n|tooLargeConfig}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `配置文件生成失败`})
|
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `${i18n|configGenerateFailed}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Header(`Accept-Ranges`, `none`)
|
ctx.Header(`Accept-Ranges`, `none`)
|
||||||
|
@@ -45,7 +45,7 @@ func checkUpdate(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
if err := ctx.ShouldBind(&form); err != nil {
|
if err := ctx.ShouldBind(&form); err != nil {
|
||||||
golog.Error(err)
|
golog.Error(err)
|
||||||
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `参数不完整`})
|
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if form.Commit == config.COMMIT {
|
if form.Commit == config.COMMIT {
|
||||||
@@ -54,7 +54,7 @@ func checkUpdate(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
tpl, err := common.BuiltFS.Open(fmt.Sprintf(`/%v_%v`, form.OS, form.Arch))
|
tpl, err := common.BuiltFS.Open(fmt.Sprintf(`/%v_%v`, form.OS, form.Arch))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.JSON(http.StatusNotFound, modules.Packet{Code: 1, Msg: `该系统或架构的客户端尚未编译`})
|
ctx.JSON(http.StatusNotFound, modules.Packet{Code: 1, Msg: `${i18n|osOrArchNotPrebuilt}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,13 +107,13 @@ func putScreenshot(ctx *gin.Context) {
|
|||||||
errMsg := ctx.GetHeader(`Error`)
|
errMsg := ctx.GetHeader(`Error`)
|
||||||
trigger := ctx.GetHeader(`Trigger`)
|
trigger := ctx.GetHeader(`Trigger`)
|
||||||
if len(trigger) == 0 {
|
if len(trigger) == 0 {
|
||||||
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `参数不完整`})
|
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(errMsg) > 0 {
|
if len(errMsg) > 0 {
|
||||||
common.CallEvent(modules.Packet{
|
common.CallEvent(modules.Packet{
|
||||||
Code: 1,
|
Code: 1,
|
||||||
Msg: fmt.Sprintf(`截图失败:%v`, errMsg),
|
Msg: fmt.Sprintf(`${i18n|screenshotFailed}: %v`, errMsg),
|
||||||
Event: trigger,
|
Event: trigger,
|
||||||
}, nil)
|
}, nil)
|
||||||
ctx.JSON(http.StatusOK, modules.Packet{Code: 0})
|
ctx.JSON(http.StatusOK, modules.Packet{Code: 0})
|
||||||
@@ -123,10 +123,10 @@ func putScreenshot(ctx *gin.Context) {
|
|||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
msg := ``
|
msg := ``
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg = fmt.Sprintf(`截图读取失败:%v`, err)
|
msg = fmt.Sprintf(`${i18n|screenshotObtainFailed}: %v`, err)
|
||||||
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: msg})
|
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: msg})
|
||||||
} else {
|
} else {
|
||||||
msg = `截图失败:未知错误`
|
msg = `${i18n|screenshotFailed}: ${i18n|unknownError}`
|
||||||
ctx.JSON(http.StatusOK, modules.Packet{Code: 0})
|
ctx.JSON(http.StatusOK, modules.Packet{Code: 0})
|
||||||
}
|
}
|
||||||
common.CallEvent(modules.Packet{
|
common.CallEvent(modules.Packet{
|
||||||
@@ -153,7 +153,7 @@ func getScreenshot(ctx *gin.Context) {
|
|||||||
Device string `json:"device" yaml:"device" form:"device"`
|
Device string `json:"device" yaml:"device" form:"device"`
|
||||||
}
|
}
|
||||||
if ctx.ShouldBind(&form) != nil || (len(form.Conn) == 0 && len(form.Device) == 0) {
|
if ctx.ShouldBind(&form) != nil || (len(form.Conn) == 0 && len(form.Device) == 0) {
|
||||||
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `参数不完整`})
|
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
target := ``
|
target := ``
|
||||||
@@ -162,13 +162,13 @@ func getScreenshot(ctx *gin.Context) {
|
|||||||
ok := false
|
ok := false
|
||||||
target, ok = common.CheckDevice(form.Device)
|
target, ok = common.CheckDevice(form.Device)
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `未找到该设备`})
|
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|deviceNotExists}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
target = form.Conn
|
target = form.Conn
|
||||||
if !common.Devices.Has(target) {
|
if !common.Devices.Has(target) {
|
||||||
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `未找到该设备`})
|
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|deviceNotExists}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,19 +179,19 @@ func getScreenshot(ctx *gin.Context) {
|
|||||||
} else {
|
} else {
|
||||||
data, ok := p.Data[`screenshot`]
|
data, ok := p.Data[`screenshot`]
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `截图获取失败`})
|
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `${i18n|screenshotObtainFailed}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
screenshot, ok := data.([]byte)
|
screenshot, ok := data.([]byte)
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `截图获取失败`})
|
ctx.JSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `${i18n|screenshotObtainFailed}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data(200, `image/png`, screenshot)
|
ctx.Data(200, `image/png`, screenshot)
|
||||||
}
|
}
|
||||||
}, target, trigger, 5*time.Second)
|
}, target, trigger, 5*time.Second)
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.JSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `响应超时`})
|
ctx.JSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +216,7 @@ func callDevice(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
act := ctx.Param(`act`)
|
act := ctx.Param(`act`)
|
||||||
if ctx.ShouldBind(&form) != nil || len(act) == 0 || (len(form.Conn) == 0 && len(form.Device) == 0) {
|
if ctx.ShouldBind(&form) != nil || len(act) == 0 || (len(form.Conn) == 0 && len(form.Device) == 0) {
|
||||||
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `参数不完整`})
|
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
connUUID := ``
|
connUUID := ``
|
||||||
@@ -225,13 +225,13 @@ func callDevice(ctx *gin.Context) {
|
|||||||
ok := false
|
ok := false
|
||||||
connUUID, ok = common.CheckDevice(form.Device)
|
connUUID, ok = common.CheckDevice(form.Device)
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `未找到该设备`})
|
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|deviceNotExists}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
connUUID = form.Conn
|
connUUID = form.Conn
|
||||||
if !common.Devices.Has(connUUID) {
|
if !common.Devices.Has(connUUID) {
|
||||||
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `未找到该设备`})
|
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|deviceNotExists}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -244,7 +244,7 @@ func callDevice(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
}, connUUID, trigger, 5*time.Second)
|
}, connUUID, trigger, 5*time.Second)
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.JSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `响应超时`})
|
ctx.JSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,7 +18,7 @@ func listDeviceProcesses(ctx *gin.Context) {
|
|||||||
Device string `json:"device" yaml:"device" form:"device"`
|
Device string `json:"device" yaml:"device" form:"device"`
|
||||||
}
|
}
|
||||||
if ctx.ShouldBind(&form) != nil || (len(form.Conn) == 0 && len(form.Device) == 0) {
|
if ctx.ShouldBind(&form) != nil || (len(form.Conn) == 0 && len(form.Device) == 0) {
|
||||||
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `参数不完整`})
|
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
connUUID := ``
|
connUUID := ``
|
||||||
@@ -27,13 +27,13 @@ func listDeviceProcesses(ctx *gin.Context) {
|
|||||||
ok := false
|
ok := false
|
||||||
connUUID, ok = common.CheckDevice(form.Device)
|
connUUID, ok = common.CheckDevice(form.Device)
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `未找到该设备`})
|
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|deviceNotExists}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
connUUID = form.Conn
|
connUUID = form.Conn
|
||||||
if !common.Devices.Has(connUUID) {
|
if !common.Devices.Has(connUUID) {
|
||||||
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `未找到该设备`})
|
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|deviceNotExists}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ func listDeviceProcesses(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
}, connUUID, trigger, 5*time.Second)
|
}, connUUID, trigger, 5*time.Second)
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.JSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `响应超时`})
|
ctx.JSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ func killDeviceProcess(ctx *gin.Context) {
|
|||||||
Device string `json:"device" yaml:"device" form:"device"`
|
Device string `json:"device" yaml:"device" form:"device"`
|
||||||
}
|
}
|
||||||
if ctx.ShouldBind(&form) != nil || (len(form.Conn) == 0 && len(form.Device) == 0) {
|
if ctx.ShouldBind(&form) != nil || (len(form.Conn) == 0 && len(form.Device) == 0) {
|
||||||
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `参数不完整`})
|
ctx.JSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
target := ``
|
target := ``
|
||||||
@@ -68,13 +68,13 @@ func killDeviceProcess(ctx *gin.Context) {
|
|||||||
ok := false
|
ok := false
|
||||||
target, ok = common.CheckDevice(form.Device)
|
target, ok = common.CheckDevice(form.Device)
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `未找到该设备`})
|
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|deviceNotExists}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
target = form.Conn
|
target = form.Conn
|
||||||
if !common.Devices.Has(target) {
|
if !common.Devices.Has(target) {
|
||||||
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `未找到该设备`})
|
ctx.JSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|deviceNotExists}`})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,6 +87,6 @@ func killDeviceProcess(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
}, target, trigger, 5*time.Second)
|
}, target, trigger, 5*time.Second)
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.JSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `响应超时`})
|
ctx.JSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,31 +29,31 @@ func init() {
|
|||||||
wsTerminals.HandleConnect(func(session *melody.Session) {
|
wsTerminals.HandleConnect(func(session *melody.Session) {
|
||||||
device, ok := session.Get(`Device`)
|
device, ok := session.Get(`Device`)
|
||||||
if !ok {
|
if !ok {
|
||||||
simpleSendPack(modules.Packet{Act: `warn`, Msg: `终端创建失败`}, session)
|
simpleSendPack(modules.Packet{Act: `warn`, Msg: `${i18n|terminalSessionCreationFailed}`}, session)
|
||||||
session.Close()
|
session.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val, ok := session.Get(`Terminal`)
|
val, ok := session.Get(`Terminal`)
|
||||||
if !ok {
|
if !ok {
|
||||||
simpleSendPack(modules.Packet{Act: `warn`, Msg: `终端创建失败`}, session)
|
simpleSendPack(modules.Packet{Act: `warn`, Msg: `${i18n|terminalSessionCreationFailed}`}, session)
|
||||||
session.Close()
|
session.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
termUUID, ok := val.(string)
|
termUUID, ok := val.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
simpleSendPack(modules.Packet{Act: `warn`, Msg: `终端创建失败`}, session)
|
simpleSendPack(modules.Packet{Act: `warn`, Msg: `${i18n|terminalSessionCreationFailed}`}, session)
|
||||||
session.Close()
|
session.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
connUUID, ok := common.CheckDevice(device.(string))
|
connUUID, ok := common.CheckDevice(device.(string))
|
||||||
if !ok {
|
if !ok {
|
||||||
simpleSendPack(modules.Packet{Act: `warn`, Msg: `设备不存在或已经离线`}, session)
|
simpleSendPack(modules.Packet{Act: `warn`, Msg: `${i18n|deviceNotExists}`}, session)
|
||||||
session.Close()
|
session.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
deviceConn, ok := common.Melody.GetSessionByUUID(connUUID)
|
deviceConn, ok := common.Melody.GetSessionByUUID(connUUID)
|
||||||
if !ok {
|
if !ok {
|
||||||
simpleSendPack(modules.Packet{Act: `warn`, Msg: `设备不存在或已经离线`}, session)
|
simpleSendPack(modules.Packet{Act: `warn`, Msg: `${i18n|deviceNotExists}`}, session)
|
||||||
session.Close()
|
session.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ func init() {
|
|||||||
go common.WSHealthCheck(wsTerminals)
|
go common.WSHealthCheck(wsTerminals)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initTerminal 负责处理terminal的websocket握手事务
|
// initTerminal handles terminal websocket handshake event
|
||||||
func initTerminal(ctx *gin.Context) {
|
func initTerminal(ctx *gin.Context) {
|
||||||
if !ctx.IsWebsocket() {
|
if !ctx.IsWebsocket() {
|
||||||
ctx.Status(http.StatusUpgradeRequired)
|
ctx.Status(http.StatusUpgradeRequired)
|
||||||
@@ -133,15 +133,17 @@ func initTerminal(ctx *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// eventWrapper 会包装一个eventCb,当收到与浏览器session对应的device响应时,
|
// eventWrapper returns a eventCb function that will be called when
|
||||||
// 会自动把数据转发给浏览器端
|
// device need to send a packet to browser terminal
|
||||||
func eventWrapper(terminal *terminal) common.EventCallback {
|
func eventWrapper(terminal *terminal) common.EventCallback {
|
||||||
return func(pack modules.Packet, device *melody.Session) {
|
return func(pack modules.Packet, device *melody.Session) {
|
||||||
if pack.Act == `initTerminal` {
|
if pack.Act == `initTerminal` {
|
||||||
if pack.Code != 0 {
|
if pack.Code != 0 {
|
||||||
msg := `终端创建失败:未知错误`
|
msg := `${i18n|terminalSessionCreationFailed}`
|
||||||
if len(pack.Msg) > 0 {
|
if len(pack.Msg) > 0 {
|
||||||
msg = `终端创建失败:` + pack.Msg
|
msg += pack.Msg
|
||||||
|
} else {
|
||||||
|
msg += `${i18n|unknownError}`
|
||||||
}
|
}
|
||||||
simpleSendPack(modules.Packet{Act: `warn`, Msg: msg}, terminal.session)
|
simpleSendPack(modules.Packet{Act: `warn`, Msg: msg}, terminal.session)
|
||||||
terminals.Remove(terminal.termUUID)
|
terminals.Remove(terminal.termUUID)
|
||||||
@@ -151,7 +153,7 @@ func eventWrapper(terminal *terminal) common.EventCallback {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if pack.Act == `quitTerminal` {
|
if pack.Act == `quitTerminal` {
|
||||||
msg := `终端已退出`
|
msg := `${i18n|terminalSessionClosed}`
|
||||||
if len(pack.Msg) > 0 {
|
if len(pack.Msg) > 0 {
|
||||||
msg = pack.Msg
|
msg = pack.Msg
|
||||||
}
|
}
|
||||||
|
@@ -34,16 +34,16 @@ func main() {
|
|||||||
|
|
||||||
data, err := ioutil.ReadFile(`./Config.json`)
|
data, err := ioutil.ReadFile(`./Config.json`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Fatal(`读取配置文件失败:`, err)
|
golog.Fatal(`Failed to read config file: `, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = utils.JSON.Unmarshal(data, &config.Config)
|
err = utils.JSON.Unmarshal(data, &config.Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Fatal(`解析配置文件失败:`, err)
|
golog.Fatal(`Failed to parse config file: `, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(config.Config.Salt) > 24 {
|
if len(config.Config.Salt) > 24 {
|
||||||
golog.Fatal(`Salt的长度不能超过24位`)
|
golog.Fatal(`Length of Salt should be less than 24.`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
config.Config.StdSalt = []byte(config.Config.Salt)
|
config.Config.StdSalt = []byte(config.Config.Salt)
|
||||||
@@ -52,12 +52,12 @@ func main() {
|
|||||||
|
|
||||||
webFS, err := fs.NewWithNamespace(`web`)
|
webFS, err := fs.NewWithNamespace(`web`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Fatal(`加载静态资源失败:`, err)
|
golog.Fatal(`Failed to load static resources: `, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
common.BuiltFS, err = fs.NewWithNamespace(`built`)
|
common.BuiltFS, err = fs.NewWithNamespace(`built`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Fatal(`加载预编译客户端失败:`, err)
|
golog.Fatal(`Failed to load prebuilt clients: `, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
app := gin.New()
|
app := gin.New()
|
||||||
@@ -81,7 +81,7 @@ func main() {
|
|||||||
golog.Fatal(`Failed to bind address: `, err)
|
golog.Fatal(`Failed to bind address: `, err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
quit := make(chan os.Signal)
|
quit := make(chan os.Signal, 3)
|
||||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||||
<-quit
|
<-quit
|
||||||
golog.Warn(`Server is shutting down ...`)
|
golog.Warn(`Server is shutting down ...`)
|
||||||
@@ -91,9 +91,7 @@ func main() {
|
|||||||
if err := srv.Shutdown(ctx); err != nil {
|
if err := srv.Shutdown(ctx); err != nil {
|
||||||
golog.Fatal(`Server shutdown: `, err)
|
golog.Fatal(`Server shutdown: `, err)
|
||||||
}
|
}
|
||||||
select {
|
<-ctx.Done()
|
||||||
case <-ctx.Done():
|
|
||||||
}
|
|
||||||
golog.Info(`Server exited,`)
|
golog.Info(`Server exited,`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
396
web/package-lock.json
generated
396
web/package-lock.json
generated
@@ -169,38 +169,128 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/compat-data": {
|
"@babel/compat-data": {
|
||||||
"version": "7.17.0",
|
"version": "7.17.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz",
|
||||||
"integrity": "sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==",
|
"integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@babel/core": {
|
"@babel/core": {
|
||||||
"version": "7.17.5",
|
"version": "7.17.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.9.tgz",
|
||||||
"integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==",
|
"integrity": "sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ampproject/remapping": "^2.1.0",
|
"@ampproject/remapping": "^2.1.0",
|
||||||
"@babel/code-frame": "^7.16.7",
|
"@babel/code-frame": "^7.16.7",
|
||||||
"@babel/generator": "^7.17.3",
|
"@babel/generator": "^7.17.9",
|
||||||
"@babel/helper-compilation-targets": "^7.16.7",
|
"@babel/helper-compilation-targets": "^7.17.7",
|
||||||
"@babel/helper-module-transforms": "^7.16.7",
|
"@babel/helper-module-transforms": "^7.17.7",
|
||||||
"@babel/helpers": "^7.17.2",
|
"@babel/helpers": "^7.17.9",
|
||||||
"@babel/parser": "^7.17.3",
|
"@babel/parser": "^7.17.9",
|
||||||
"@babel/template": "^7.16.7",
|
"@babel/template": "^7.16.7",
|
||||||
"@babel/traverse": "^7.17.3",
|
"@babel/traverse": "^7.17.9",
|
||||||
"@babel/types": "^7.17.0",
|
"@babel/types": "^7.17.0",
|
||||||
"convert-source-map": "^1.7.0",
|
"convert-source-map": "^1.7.0",
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
"gensync": "^1.0.0-beta.2",
|
"gensync": "^1.0.0-beta.2",
|
||||||
"json5": "^2.1.2",
|
"json5": "^2.2.1",
|
||||||
"semver": "^6.3.0"
|
"semver": "^6.3.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/compat-data": {
|
||||||
|
"version": "7.17.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz",
|
||||||
|
"integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@babel/generator": {
|
||||||
|
"version": "7.17.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.9.tgz",
|
||||||
|
"integrity": "sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/types": "^7.17.0",
|
||||||
|
"jsesc": "^2.5.1",
|
||||||
|
"source-map": "^0.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@babel/helper-compilation-targets": {
|
||||||
|
"version": "7.17.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz",
|
||||||
|
"integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/compat-data": "^7.17.7",
|
||||||
|
"@babel/helper-validator-option": "^7.16.7",
|
||||||
|
"browserslist": "^4.17.5",
|
||||||
|
"semver": "^6.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@babel/helper-function-name": {
|
||||||
|
"version": "7.17.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz",
|
||||||
|
"integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/template": "^7.16.7",
|
||||||
|
"@babel/types": "^7.17.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@babel/helper-module-transforms": {
|
||||||
|
"version": "7.17.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz",
|
||||||
|
"integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/helper-environment-visitor": "^7.16.7",
|
||||||
|
"@babel/helper-module-imports": "^7.16.7",
|
||||||
|
"@babel/helper-simple-access": "^7.17.7",
|
||||||
|
"@babel/helper-split-export-declaration": "^7.16.7",
|
||||||
|
"@babel/helper-validator-identifier": "^7.16.7",
|
||||||
|
"@babel/template": "^7.16.7",
|
||||||
|
"@babel/traverse": "^7.17.3",
|
||||||
|
"@babel/types": "^7.17.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@babel/helper-simple-access": {
|
||||||
|
"version": "7.17.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz",
|
||||||
|
"integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/types": "^7.17.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@babel/parser": {
|
||||||
|
"version": "7.17.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz",
|
||||||
|
"integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@babel/traverse": {
|
||||||
|
"version": "7.17.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.9.tgz",
|
||||||
|
"integrity": "sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/code-frame": "^7.16.7",
|
||||||
|
"@babel/generator": "^7.17.9",
|
||||||
|
"@babel/helper-environment-visitor": "^7.16.7",
|
||||||
|
"@babel/helper-function-name": "^7.17.9",
|
||||||
|
"@babel/helper-hoist-variables": "^7.16.7",
|
||||||
|
"@babel/helper-split-export-declaration": "^7.16.7",
|
||||||
|
"@babel/parser": "^7.17.9",
|
||||||
|
"@babel/types": "^7.17.0",
|
||||||
|
"debug": "^4.1.0",
|
||||||
|
"globals": "^11.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/generator": {
|
"@babel/generator": {
|
||||||
"version": "7.17.3",
|
"version": "7.17.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.9.tgz",
|
||||||
"integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==",
|
"integrity": "sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/types": "^7.17.0",
|
"@babel/types": "^7.17.0",
|
||||||
@@ -228,27 +318,27 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/helper-compilation-targets": {
|
"@babel/helper-compilation-targets": {
|
||||||
"version": "7.16.7",
|
"version": "7.17.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz",
|
||||||
"integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==",
|
"integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/compat-data": "^7.16.4",
|
"@babel/compat-data": "^7.17.7",
|
||||||
"@babel/helper-validator-option": "^7.16.7",
|
"@babel/helper-validator-option": "^7.16.7",
|
||||||
"browserslist": "^4.17.5",
|
"browserslist": "^4.17.5",
|
||||||
"semver": "^6.3.0"
|
"semver": "^6.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/helper-create-class-features-plugin": {
|
"@babel/helper-create-class-features-plugin": {
|
||||||
"version": "7.17.6",
|
"version": "7.17.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.9.tgz",
|
||||||
"integrity": "sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==",
|
"integrity": "sha512-kUjip3gruz6AJKOq5i3nC6CoCEEF/oHH3cp6tOZhB+IyyyPyW0g1Gfsxn3mkk6S08pIA2y8GQh609v9G/5sHVQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/helper-annotate-as-pure": "^7.16.7",
|
"@babel/helper-annotate-as-pure": "^7.16.7",
|
||||||
"@babel/helper-environment-visitor": "^7.16.7",
|
"@babel/helper-environment-visitor": "^7.16.7",
|
||||||
"@babel/helper-function-name": "^7.16.7",
|
"@babel/helper-function-name": "^7.17.9",
|
||||||
"@babel/helper-member-expression-to-functions": "^7.16.7",
|
"@babel/helper-member-expression-to-functions": "^7.17.7",
|
||||||
"@babel/helper-optimise-call-expression": "^7.16.7",
|
"@babel/helper-optimise-call-expression": "^7.16.7",
|
||||||
"@babel/helper-replace-supers": "^7.16.7",
|
"@babel/helper-replace-supers": "^7.16.7",
|
||||||
"@babel/helper-split-export-declaration": "^7.16.7"
|
"@babel/helper-split-export-declaration": "^7.16.7"
|
||||||
@@ -299,23 +389,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/helper-function-name": {
|
"@babel/helper-function-name": {
|
||||||
"version": "7.16.7",
|
"version": "7.17.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz",
|
||||||
"integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==",
|
"integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/helper-get-function-arity": "^7.16.7",
|
|
||||||
"@babel/template": "^7.16.7",
|
"@babel/template": "^7.16.7",
|
||||||
"@babel/types": "^7.16.7"
|
"@babel/types": "^7.17.0"
|
||||||
}
|
|
||||||
},
|
|
||||||
"@babel/helper-get-function-arity": {
|
|
||||||
"version": "7.16.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz",
|
|
||||||
"integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"@babel/types": "^7.16.7"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/helper-hoist-variables": {
|
"@babel/helper-hoist-variables": {
|
||||||
@@ -328,12 +408,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/helper-member-expression-to-functions": {
|
"@babel/helper-member-expression-to-functions": {
|
||||||
"version": "7.16.7",
|
"version": "7.17.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz",
|
||||||
"integrity": "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==",
|
"integrity": "sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/types": "^7.16.7"
|
"@babel/types": "^7.17.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/helper-module-imports": {
|
"@babel/helper-module-imports": {
|
||||||
@@ -346,14 +426,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/helper-module-transforms": {
|
"@babel/helper-module-transforms": {
|
||||||
"version": "7.17.6",
|
"version": "7.17.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz",
|
||||||
"integrity": "sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA==",
|
"integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/helper-environment-visitor": "^7.16.7",
|
"@babel/helper-environment-visitor": "^7.16.7",
|
||||||
"@babel/helper-module-imports": "^7.16.7",
|
"@babel/helper-module-imports": "^7.16.7",
|
||||||
"@babel/helper-simple-access": "^7.16.7",
|
"@babel/helper-simple-access": "^7.17.7",
|
||||||
"@babel/helper-split-export-declaration": "^7.16.7",
|
"@babel/helper-split-export-declaration": "^7.16.7",
|
||||||
"@babel/helper-validator-identifier": "^7.16.7",
|
"@babel/helper-validator-identifier": "^7.16.7",
|
||||||
"@babel/template": "^7.16.7",
|
"@babel/template": "^7.16.7",
|
||||||
@@ -401,12 +481,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/helper-simple-access": {
|
"@babel/helper-simple-access": {
|
||||||
"version": "7.16.7",
|
"version": "7.17.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz",
|
||||||
"integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==",
|
"integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/types": "^7.16.7"
|
"@babel/types": "^7.17.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/helper-skip-transparent-expression-wrappers": {
|
"@babel/helper-skip-transparent-expression-wrappers": {
|
||||||
@@ -452,14 +532,61 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/helpers": {
|
"@babel/helpers": {
|
||||||
"version": "7.17.2",
|
"version": "7.17.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz",
|
||||||
"integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==",
|
"integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/template": "^7.16.7",
|
"@babel/template": "^7.16.7",
|
||||||
"@babel/traverse": "^7.17.0",
|
"@babel/traverse": "^7.17.9",
|
||||||
"@babel/types": "^7.17.0"
|
"@babel/types": "^7.17.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/generator": {
|
||||||
|
"version": "7.17.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.9.tgz",
|
||||||
|
"integrity": "sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/types": "^7.17.0",
|
||||||
|
"jsesc": "^2.5.1",
|
||||||
|
"source-map": "^0.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@babel/helper-function-name": {
|
||||||
|
"version": "7.17.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz",
|
||||||
|
"integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/template": "^7.16.7",
|
||||||
|
"@babel/types": "^7.17.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@babel/parser": {
|
||||||
|
"version": "7.17.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz",
|
||||||
|
"integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@babel/traverse": {
|
||||||
|
"version": "7.17.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.9.tgz",
|
||||||
|
"integrity": "sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/code-frame": "^7.16.7",
|
||||||
|
"@babel/generator": "^7.17.9",
|
||||||
|
"@babel/helper-environment-visitor": "^7.16.7",
|
||||||
|
"@babel/helper-function-name": "^7.17.9",
|
||||||
|
"@babel/helper-hoist-variables": "^7.16.7",
|
||||||
|
"@babel/helper-split-export-declaration": "^7.16.7",
|
||||||
|
"@babel/parser": "^7.17.9",
|
||||||
|
"@babel/types": "^7.17.0",
|
||||||
|
"debug": "^4.1.0",
|
||||||
|
"globals": "^11.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/highlight": {
|
"@babel/highlight": {
|
||||||
@@ -856,9 +983,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/plugin-transform-destructuring": {
|
"@babel/plugin-transform-destructuring": {
|
||||||
"version": "7.17.3",
|
"version": "7.17.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.7.tgz",
|
||||||
"integrity": "sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==",
|
"integrity": "sha512-XVh0r5yq9sLR4vZ6eVZe8FKfIcSgaTBxVBRSYokRj2qksf6QerYnTxz9/GTuKTH/n/HwLP7t6gtlybHetJ/6hQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/helper-plugin-utils": "^7.16.7"
|
"@babel/helper-plugin-utils": "^7.16.7"
|
||||||
@@ -943,25 +1070,25 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/plugin-transform-modules-commonjs": {
|
"@babel/plugin-transform-modules-commonjs": {
|
||||||
"version": "7.16.8",
|
"version": "7.17.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.17.9.tgz",
|
||||||
"integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==",
|
"integrity": "sha512-2TBFd/r2I6VlYn0YRTz2JdazS+FoUuQ2rIFHoAxtyP/0G3D82SBLaRq9rnUkpqlLg03Byfl/+M32mpxjO6KaPw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/helper-module-transforms": "^7.16.7",
|
"@babel/helper-module-transforms": "^7.17.7",
|
||||||
"@babel/helper-plugin-utils": "^7.16.7",
|
"@babel/helper-plugin-utils": "^7.16.7",
|
||||||
"@babel/helper-simple-access": "^7.16.7",
|
"@babel/helper-simple-access": "^7.17.7",
|
||||||
"babel-plugin-dynamic-import-node": "^2.3.3"
|
"babel-plugin-dynamic-import-node": "^2.3.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/plugin-transform-modules-systemjs": {
|
"@babel/plugin-transform-modules-systemjs": {
|
||||||
"version": "7.16.7",
|
"version": "7.17.8",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.17.8.tgz",
|
||||||
"integrity": "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==",
|
"integrity": "sha512-39reIkMTUVagzgA5x88zDYXPCMT6lcaRKs1+S9K6NKBPErbgO/w/kP8GlNQTC87b412ZTlmNgr3k2JrWgHH+Bw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/helper-hoist-variables": "^7.16.7",
|
"@babel/helper-hoist-variables": "^7.16.7",
|
||||||
"@babel/helper-module-transforms": "^7.16.7",
|
"@babel/helper-module-transforms": "^7.17.7",
|
||||||
"@babel/helper-plugin-utils": "^7.16.7",
|
"@babel/helper-plugin-utils": "^7.16.7",
|
||||||
"@babel/helper-validator-identifier": "^7.16.7",
|
"@babel/helper-validator-identifier": "^7.16.7",
|
||||||
"babel-plugin-dynamic-import-node": "^2.3.3"
|
"babel-plugin-dynamic-import-node": "^2.3.3"
|
||||||
@@ -1065,12 +1192,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/plugin-transform-regenerator": {
|
"@babel/plugin-transform-regenerator": {
|
||||||
"version": "7.16.7",
|
"version": "7.17.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.17.9.tgz",
|
||||||
"integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==",
|
"integrity": "sha512-Lc2TfbxR1HOyn/c6b4Y/b6NHoTb67n/IoWLxTu4kC7h4KQnWlhCq2S8Tx0t2SVvv5Uu87Hs+6JEJ5kt2tYGylQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"regenerator-transform": "^0.14.2"
|
"regenerator-transform": "^0.15.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/plugin-transform-reserved-words": {
|
"@babel/plugin-transform-reserved-words": {
|
||||||
@@ -1276,21 +1403,29 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/traverse": {
|
"@babel/traverse": {
|
||||||
"version": "7.17.3",
|
"version": "7.17.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.9.tgz",
|
||||||
"integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==",
|
"integrity": "sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/code-frame": "^7.16.7",
|
"@babel/code-frame": "^7.16.7",
|
||||||
"@babel/generator": "^7.17.3",
|
"@babel/generator": "^7.17.9",
|
||||||
"@babel/helper-environment-visitor": "^7.16.7",
|
"@babel/helper-environment-visitor": "^7.16.7",
|
||||||
"@babel/helper-function-name": "^7.16.7",
|
"@babel/helper-function-name": "^7.17.9",
|
||||||
"@babel/helper-hoist-variables": "^7.16.7",
|
"@babel/helper-hoist-variables": "^7.16.7",
|
||||||
"@babel/helper-split-export-declaration": "^7.16.7",
|
"@babel/helper-split-export-declaration": "^7.16.7",
|
||||||
"@babel/parser": "^7.17.3",
|
"@babel/parser": "^7.17.9",
|
||||||
"@babel/types": "^7.17.0",
|
"@babel/types": "^7.17.0",
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
"globals": "^11.1.0"
|
"globals": "^11.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/parser": {
|
||||||
|
"version": "7.17.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz",
|
||||||
|
"integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/types": {
|
"@babel/types": {
|
||||||
@@ -1989,21 +2124,21 @@
|
|||||||
"integrity": "sha512-Pj2IR7u8hmUEDOwB++su6baaRi+QvsgajuFB9j95foM1N2gy5HM4z60hfusIO0fBPG5uLAEl6yCJr1jNSVugEQ=="
|
"integrity": "sha512-Pj2IR7u8hmUEDOwB++su6baaRi+QvsgajuFB9j95foM1N2gy5HM4z60hfusIO0fBPG5uLAEl6yCJr1jNSVugEQ=="
|
||||||
},
|
},
|
||||||
"axios": {
|
"axios": {
|
||||||
"version": "0.26.0",
|
"version": "0.26.1",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
|
||||||
"integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==",
|
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"follow-redirects": "^1.14.8"
|
"follow-redirects": "^1.14.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"babel-loader": {
|
"babel-loader": {
|
||||||
"version": "8.2.3",
|
"version": "8.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.4.tgz",
|
||||||
"integrity": "sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw==",
|
"integrity": "sha512-8dytA3gcvPPPv4Grjhnt8b5IIiTcq/zeXOPk4iTYI0SVXcsmuGg7JtBRDp8S9X+gJfhQ8ektjXZlDu1Bb33U8A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"find-cache-dir": "^3.3.1",
|
"find-cache-dir": "^3.3.1",
|
||||||
"loader-utils": "^1.4.0",
|
"loader-utils": "^2.0.0",
|
||||||
"make-dir": "^3.1.0",
|
"make-dir": "^3.1.0",
|
||||||
"schema-utils": "^2.6.5"
|
"schema-utils": "^2.6.5"
|
||||||
}
|
}
|
||||||
@@ -2651,9 +2786,9 @@
|
|||||||
"integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw=="
|
"integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw=="
|
||||||
},
|
},
|
||||||
"css-loader": {
|
"css-loader": {
|
||||||
"version": "6.7.0",
|
"version": "6.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz",
|
||||||
"integrity": "sha512-S7HCfCiDHLA+VXKqdZwyRZgoO0R9BnKDnVIoHMq5grl3N86zAu7MB+FBWHr5xOJC8SmvpTLha/2NpfFkFEN/ig==",
|
"integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"icss-utils": "^5.1.0",
|
"icss-utils": "^5.1.0",
|
||||||
@@ -2667,12 +2802,12 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "7.3.5",
|
"version": "7.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz",
|
||||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
"integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"lru-cache": "^6.0.0"
|
"lru-cache": "^7.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3605,6 +3740,14 @@
|
|||||||
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
|
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"i18next": {
|
||||||
|
"version": "21.6.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/i18next/-/i18next-21.6.15.tgz",
|
||||||
|
"integrity": "sha512-uMFyw5HGK9KSJ7ok/WUJfeNQj53VOR4NoITtErffWen2v2SjJfpCls7tKTLF1nTCdKRePY4lCoZMLKhRSj/1GA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.17.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"iconv-lite": {
|
"iconv-lite": {
|
||||||
"version": "0.4.24",
|
"version": "0.4.24",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
@@ -3918,13 +4061,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"json5": {
|
"json5": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
|
||||||
"integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
|
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"requires": {
|
|
||||||
"minimist": "^1.2.5"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"kind-of": {
|
"kind-of": {
|
||||||
"version": "6.0.3",
|
"version": "6.0.3",
|
||||||
@@ -3999,25 +4139,14 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"loader-utils": {
|
"loader-utils": {
|
||||||
"version": "1.4.0",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz",
|
||||||
"integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
|
"integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"big.js": "^5.2.2",
|
"big.js": "^5.2.2",
|
||||||
"emojis-list": "^3.0.0",
|
"emojis-list": "^3.0.0",
|
||||||
"json5": "^1.0.1"
|
"json5": "^2.1.2"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"json5": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
|
|
||||||
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"minimist": "^1.2.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"locate-path": {
|
"locate-path": {
|
||||||
@@ -4078,13 +4207,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lru-cache": {
|
"lru-cache": {
|
||||||
"version": "6.0.0",
|
"version": "7.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz",
|
||||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
"integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"requires": {
|
|
||||||
"yallist": "^4.0.0"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"make-dir": {
|
"make-dir": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
@@ -4271,9 +4397,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"nanoid": {
|
"nanoid": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.2.tgz",
|
||||||
"integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==",
|
"integrity": "sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"needle": {
|
"needle": {
|
||||||
@@ -4656,9 +4782,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
"version": "8.4.8",
|
"version": "8.4.12",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.8.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz",
|
||||||
"integrity": "sha512-2tXEqGxrjvAO6U+CJzDL2Fk2kPHTv1jQsYkSoMeOis2SsYaXRO2COxTdQp99cYvif9JTXaAk9lYGc3VhJt7JPQ==",
|
"integrity": "sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"nanoid": "^3.3.1",
|
"nanoid": "^3.3.1",
|
||||||
@@ -4702,9 +4828,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"postcss-selector-parser": {
|
"postcss-selector-parser": {
|
||||||
"version": "6.0.9",
|
"version": "6.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
|
||||||
"integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==",
|
"integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"cssesc": "^3.0.0",
|
"cssesc": "^3.0.0",
|
||||||
@@ -5421,9 +5547,9 @@
|
|||||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
||||||
},
|
},
|
||||||
"regenerator-transform": {
|
"regenerator-transform": {
|
||||||
"version": "0.14.5",
|
"version": "0.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz",
|
||||||
"integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==",
|
"integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/runtime": "^7.8.4"
|
"@babel/runtime": "^7.8.4"
|
||||||
@@ -6814,12 +6940,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
|
||||||
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
|
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
|
||||||
"yallist": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,9 +14,10 @@
|
|||||||
"@ant-design/pro-layout": "^6.23.0",
|
"@ant-design/pro-layout": "^6.23.0",
|
||||||
"@ant-design/pro-table": "^2.45.0",
|
"@ant-design/pro-table": "^2.45.0",
|
||||||
"antd": "^4.16.8",
|
"antd": "^4.16.8",
|
||||||
"axios": "latest",
|
"axios": "^0.26.1",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"dayjs": "^1.10.6",
|
"dayjs": "^1.10.6",
|
||||||
|
"i18next": "^21.6.15",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"qs": "^6.10.3",
|
"qs": "^6.10.3",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
@@ -29,19 +30,19 @@
|
|||||||
"xterm-addon-web-links": "^0.5.1"
|
"xterm-addon-web-links": "^0.5.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "latest",
|
"@babel/core": "^7.17.9",
|
||||||
"@babel/preset-env": "latest",
|
"@babel/preset-env": "^7.16.11",
|
||||||
"@babel/preset-react": "latest",
|
"@babel/preset-react": "^7.16.7",
|
||||||
"antd-dayjs-webpack-plugin": "^1.0.6",
|
"antd-dayjs-webpack-plugin": "^1.0.6",
|
||||||
"babel-loader": "latest",
|
"babel-loader": "^8.2.4",
|
||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"copy-webpack-plugin": "^10.2.4",
|
"copy-webpack-plugin": "^10.2.4",
|
||||||
"css-loader": "latest",
|
"css-loader": "^6.7.1",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"less": "^4.1.1",
|
"less": "^4.1.1",
|
||||||
"less-loader": "^10.0.1",
|
"less-loader": "^10.0.1",
|
||||||
"react-text-loop": "^2.3.0",
|
"react-text-loop": "^2.3.0",
|
||||||
"style-loader": "latest",
|
"style-loader": "^3.3.1",
|
||||||
"uglifyjs-webpack-plugin": "^2.2.0",
|
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||||
"webpack": "^5.18.0",
|
"webpack": "^5.18.0",
|
||||||
"webpack-cli": "^4.4.0",
|
"webpack-cli": "^4.4.0",
|
||||||
|
@@ -2,8 +2,9 @@ import React, {useEffect, useRef, useState} from 'react';
|
|||||||
import {message, Modal, Popconfirm} from "antd";
|
import {message, Modal, Popconfirm} from "antd";
|
||||||
import ProTable from '@ant-design/pro-table';
|
import ProTable from '@ant-design/pro-table';
|
||||||
import {formatSize, post, request, waitTime} from "../utils/utils";
|
import {formatSize, post, request, waitTime} from "../utils/utils";
|
||||||
import './browser.css';
|
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import i18n from "../locale/locale";
|
||||||
|
import './explorer.css';
|
||||||
|
|
||||||
function FileBrowser(props) {
|
function FileBrowser(props) {
|
||||||
const [path, setPath] = useState(`/`);
|
const [path, setPath] = useState(`/`);
|
||||||
@@ -11,14 +12,14 @@ function FileBrowser(props) {
|
|||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
key: 'Name',
|
key: 'Name',
|
||||||
title: 'Name',
|
title: i18n.t('fileName'),
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 180
|
width: 180
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'Size',
|
key: 'Size',
|
||||||
title: 'Size',
|
title: i18n.t('fileSize'),
|
||||||
dataIndex: 'size',
|
dataIndex: 'size',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 60,
|
width: 60,
|
||||||
@@ -26,16 +27,16 @@ function FileBrowser(props) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'Time',
|
key: 'Time',
|
||||||
title: 'Time Modified',
|
title: i18n.t('modifyTime'),
|
||||||
dataIndex: 'time',
|
dataIndex: 'time',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 100,
|
width: 100,
|
||||||
renderText: (ts, file) => file.type === 0 ? dayjs.unix(ts).format('YYYY/MM/DD HH:mm') : '-'
|
renderText: (ts, file) => file.type === 0 ? dayjs.unix(ts).format(i18n.t('dateTimeFormat')) : '-'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'Option',
|
key: 'Option',
|
||||||
width: 120,
|
width: 120,
|
||||||
title: '操作',
|
title: '',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
valueType: 'option',
|
valueType: 'option',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
@@ -59,10 +60,14 @@ function FileBrowser(props) {
|
|||||||
let remove = (
|
let remove = (
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
key='remove'
|
key='remove'
|
||||||
title={'确定要删除该' + (file.type === 0 ? '文件' : '目录') + '吗?'}
|
title={
|
||||||
|
i18n.t('deleteConfirm').replace('{0}',
|
||||||
|
i18n.t(file.type === 0 ? 'file' : 'folder')
|
||||||
|
)
|
||||||
|
}
|
||||||
onConfirm={removeFile.bind(null, file.name)}
|
onConfirm={removeFile.bind(null, file.name)}
|
||||||
>
|
>
|
||||||
<a>删除</a>
|
<a>{i18n.t('delete')}</a>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
);
|
);
|
||||||
switch (file.type) {
|
switch (file.type) {
|
||||||
@@ -71,7 +76,7 @@ function FileBrowser(props) {
|
|||||||
<a
|
<a
|
||||||
key='download'
|
key='download'
|
||||||
onClick={downloadFile.bind(null, file.name)}
|
onClick={downloadFile.bind(null, file.name)}
|
||||||
>下载</a>,
|
>{i18n.t('download')}</a>,
|
||||||
remove,
|
remove,
|
||||||
];
|
];
|
||||||
case 1:
|
case 1:
|
||||||
@@ -127,10 +132,10 @@ function FileBrowser(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function removeFile(file) {
|
function removeFile(file) {
|
||||||
request(`/api/device/file/remove`, {path: path+file, device: props.device}).then(res => {
|
request(`/api/device/file/remove`, {path: path + file, device: props.device}).then(res => {
|
||||||
let data = res.data;
|
let data = res.data;
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
message.success('文件或目录已被删除');
|
message.success(i18n.t('deleteSuccess'));
|
||||||
tableRef.current.reload();
|
tableRef.current.reload();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -156,7 +161,7 @@ function FileBrowser(props) {
|
|||||||
return ({
|
return ({
|
||||||
data: data.data.files,
|
data: data.data.files,
|
||||||
success: true,
|
success: true,
|
||||||
total: data.data.files.length - (addParentShortcut?1:0)
|
total: data.data.files.length - (addParentShortcut ? 1 : 0)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setPath(getLastPath());
|
setPath(getLastPath());
|
||||||
@@ -166,7 +171,7 @@ function FileBrowser(props) {
|
|||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
destroyOnClose={true}
|
destroyOnClose={true}
|
||||||
title='File Explorer'
|
title={i18n.t('fileExplorer')}
|
||||||
footer={null}
|
footer={null}
|
||||||
height={500}
|
height={500}
|
||||||
width={800}
|
width={800}
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|||||||
import {ModalForm, ProFormCascader, ProFormDigit, ProFormGroup, ProFormText} from '@ant-design/pro-form';
|
import {ModalForm, ProFormCascader, ProFormDigit, ProFormGroup, ProFormText} from '@ant-design/pro-form';
|
||||||
import {post, request} from "../utils/utils";
|
import {post, request} from "../utils/utils";
|
||||||
import prebuilt from '../config/prebuilt.json';
|
import prebuilt from '../config/prebuilt.json';
|
||||||
|
import i18n from "../locale/locale";
|
||||||
|
|
||||||
function Generate(props) {
|
function Generate(props) {
|
||||||
const initValues = getInitValues();
|
const initValues = getInitValues();
|
||||||
@@ -50,7 +51,7 @@ function Generate(props) {
|
|||||||
<ProFormText
|
<ProFormText
|
||||||
width="md"
|
width="md"
|
||||||
name="host"
|
name="host"
|
||||||
label="Host"
|
label={i18n.t('host')}
|
||||||
rules={[{
|
rules={[{
|
||||||
required: true
|
required: true
|
||||||
}]}
|
}]}
|
||||||
@@ -58,7 +59,7 @@ function Generate(props) {
|
|||||||
<ProFormDigit
|
<ProFormDigit
|
||||||
width="md"
|
width="md"
|
||||||
name="port"
|
name="port"
|
||||||
label="Port"
|
label={i18n.t('port')}
|
||||||
min={1}
|
min={1}
|
||||||
max={65535}
|
max={65535}
|
||||||
rules={[{
|
rules={[{
|
||||||
@@ -70,7 +71,7 @@ function Generate(props) {
|
|||||||
<ProFormText
|
<ProFormText
|
||||||
width="md"
|
width="md"
|
||||||
name="path"
|
name="path"
|
||||||
label="Path"
|
label={i18n.t('path')}
|
||||||
rules={[{
|
rules={[{
|
||||||
required: true
|
required: true
|
||||||
}]}
|
}]}
|
||||||
@@ -78,7 +79,7 @@ function Generate(props) {
|
|||||||
<ProFormCascader
|
<ProFormCascader
|
||||||
width="md"
|
width="md"
|
||||||
name="ArchOS"
|
name="ArchOS"
|
||||||
label="OS & Arch"
|
label={i18n.t('osArch')}
|
||||||
request={() => prebuilt}
|
request={() => prebuilt}
|
||||||
rules={[{
|
rules={[{
|
||||||
required: true
|
required: true
|
||||||
|
@@ -2,13 +2,14 @@ import React, {useEffect, useRef, useState} from 'react';
|
|||||||
import {message, Modal, Popconfirm} from "antd";
|
import {message, Modal, Popconfirm} from "antd";
|
||||||
import ProTable from '@ant-design/pro-table';
|
import ProTable from '@ant-design/pro-table';
|
||||||
import {request, waitTime} from "../utils/utils";
|
import {request, waitTime} from "../utils/utils";
|
||||||
|
import i18n from "../locale/locale";
|
||||||
|
|
||||||
function ProcessMgr(props) {
|
function ProcessMgr(props) {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
key: 'Name',
|
key: 'Name',
|
||||||
title: 'Name',
|
title: i18n.t('procName'),
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 120
|
width: 120
|
||||||
@@ -23,7 +24,7 @@ function ProcessMgr(props) {
|
|||||||
{
|
{
|
||||||
key: 'Option',
|
key: 'Option',
|
||||||
width: 40,
|
width: 40,
|
||||||
title: '操作',
|
title: '',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
valueType: 'option',
|
valueType: 'option',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
@@ -46,10 +47,10 @@ function ProcessMgr(props) {
|
|||||||
return [
|
return [
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
key='kill'
|
key='kill'
|
||||||
title={'确定要结束该进程吗?'}
|
title={i18n.t('confirmKillProc')}
|
||||||
onConfirm={killProcess.bind(null, proc.pid)}
|
onConfirm={killProcess.bind(null, proc.pid)}
|
||||||
>
|
>
|
||||||
<a>结束</a>
|
<a>{i18n.t('killProc')}</a>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -58,7 +59,7 @@ function ProcessMgr(props) {
|
|||||||
request(`/api/device/process/kill`, {pid: pid, device: props.device}).then(res => {
|
request(`/api/device/process/kill`, {pid: pid, device: props.device}).then(res => {
|
||||||
let data = res.data;
|
let data = res.data;
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
message.success('进程已结束');
|
message.success(i18n.t('killProcSuccess'));
|
||||||
tableRef.current.reload();
|
tableRef.current.reload();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -83,7 +84,7 @@ function ProcessMgr(props) {
|
|||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
destroyOnClose={true}
|
destroyOnClose={true}
|
||||||
title='Process Manager'
|
title={i18n.t('processManager')}
|
||||||
footer={null}
|
footer={null}
|
||||||
height={500}
|
height={500}
|
||||||
width={400}
|
width={400}
|
||||||
@@ -112,7 +113,6 @@ function ProcessMgr(props) {
|
|||||||
pagination={false}
|
pagination={false}
|
||||||
actionRef={tableRef}
|
actionRef={tableRef}
|
||||||
>
|
>
|
||||||
|
|
||||||
</ProTable>
|
</ProTable>
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
)
|
||||||
|
@@ -6,6 +6,8 @@ import {FitAddon} from "xterm-addon-fit";
|
|||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import CryptoJS from 'crypto-js';
|
import CryptoJS from 'crypto-js';
|
||||||
import "xterm/css/xterm.css";
|
import "xterm/css/xterm.css";
|
||||||
|
import i18n from "../locale/locale";
|
||||||
|
import {translate} from "../utils/utils";
|
||||||
|
|
||||||
function hex2buf(hex) {
|
function hex2buf(hex) {
|
||||||
if (typeof hex !== 'string') {
|
if (typeof hex !== 'string') {
|
||||||
@@ -121,7 +123,7 @@ class TerminalModal extends React.Component {
|
|||||||
termEv = this.term.onData((e) => {
|
termEv = this.term.onData((e) => {
|
||||||
if (!this.conn) {
|
if (!this.conn) {
|
||||||
if (e === '\r' || e === ' ') {
|
if (e === '\r' || e === ' ') {
|
||||||
this.term.write('\n正在重新连接...\n');
|
this.term.write(`\n${i18n.t('reconnecting')}\n`);
|
||||||
this.termEv = this.initialize(termEv);
|
this.termEv = this.initialize(termEv);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -172,20 +174,20 @@ class TerminalModal extends React.Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (data?.act === 'warn') {
|
if (data?.act === 'warn') {
|
||||||
message.warn(data.msg??'未知错误');
|
message.warn(data.msg ? translate(data.msg) : i18n.t('unknownError'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.ws.onclose = (e) => {
|
this.ws.onclose = (e) => {
|
||||||
if (this.conn) {
|
if (this.conn) {
|
||||||
this.conn = false;
|
this.conn = false;
|
||||||
this.term.write('\n连接已断开!\n');
|
this.term.write(`\n${i18n.t('disconnected')}\n`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.ws.onerror = (e) => {
|
this.ws.onerror = (e) => {
|
||||||
if (this.conn) {
|
if (this.conn) {
|
||||||
this.conn = false;
|
this.conn = false;
|
||||||
this.term.write('\n连接已断开!\n');
|
this.term.write(`\n${i18n.t('disconnected')}\n`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return termEv;
|
return termEv;
|
||||||
@@ -285,7 +287,7 @@ class TerminalModal extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title='Terminal'
|
title={i18n.t('terminal')}
|
||||||
visible={this.props.visible}
|
visible={this.props.visible}
|
||||||
onCancel={this.props.onCancel}
|
onCancel={this.props.onCancel}
|
||||||
destroyOnClose={false}
|
destroyOnClose={false}
|
||||||
|
@@ -1,5 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ProLayout, {PageContainer} from '@ant-design/pro-layout';
|
import ProLayout, {PageContainer} from '@ant-design/pro-layout';
|
||||||
|
import zhCN from 'antd/lib/locale/zh_CN';
|
||||||
|
import en from 'antd/lib/locale/en_US';
|
||||||
|
import {getLang} from "../locale/locale";
|
||||||
|
import {ConfigProvider} from "antd";
|
||||||
import './wrapper.css';
|
import './wrapper.css';
|
||||||
|
|
||||||
function wrapper(props) {
|
function wrapper(props) {
|
||||||
@@ -15,7 +19,9 @@ function wrapper(props) {
|
|||||||
collapsedButtonRender={Title}
|
collapsedButtonRender={Title}
|
||||||
>
|
>
|
||||||
<PageContainer>
|
<PageContainer>
|
||||||
{props.children}
|
<ConfigProvider locale={getLang()==='zh-CN'?zhCN:en}>
|
||||||
|
{props.children}
|
||||||
|
</ConfigProvider>
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
</ProLayout>
|
</ProLayout>
|
||||||
);
|
);
|
||||||
|
@@ -1,3 +1,7 @@
|
|||||||
|
body {
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
#root {
|
#root {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-image: url('static/bg.svg');
|
background-image: url('static/bg.svg');
|
||||||
|
@@ -5,21 +5,19 @@ import Wrapper from './components/wrapper';
|
|||||||
import Err from './pages/404';
|
import Err from './pages/404';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import {message} from 'antd';
|
import {message} from 'antd';
|
||||||
import dayjs from 'dayjs';
|
import i18n from "./locale/locale";
|
||||||
|
|
||||||
import './global.css';
|
import './global.css';
|
||||||
import 'antd/dist/antd.css';
|
import 'antd/dist/antd.css';
|
||||||
import 'dayjs/locale/zh-cn';
|
|
||||||
import Overview from "./pages/overview";
|
import Overview from "./pages/overview";
|
||||||
|
import {translate} from "./utils/utils";
|
||||||
dayjs.locale('zh-cn');
|
|
||||||
|
|
||||||
axios.defaults.baseURL = '.';
|
axios.defaults.baseURL = '.';
|
||||||
axios.interceptors.response.use(async (res) => {
|
axios.interceptors.response.use(async (res) => {
|
||||||
let data = res.data;
|
let data = res.data;
|
||||||
if (data.hasOwnProperty('code')) {
|
if (data.hasOwnProperty('code')) {
|
||||||
if (data.code !== 0){
|
if (data.code !== 0){
|
||||||
message.warn(data.msg);
|
message.warn(translate(data.msg));
|
||||||
} else {
|
} else {
|
||||||
// The first request will ask user to provide user/pass.
|
// The first request will ask user to provide user/pass.
|
||||||
// If set timeout at the beginning, then timeout warning
|
// If set timeout at the beginning, then timeout warning
|
||||||
@@ -30,14 +28,14 @@ axios.interceptors.response.use(async (res) => {
|
|||||||
return Promise.resolve(res);
|
return Promise.resolve(res);
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
if (err.code === 'ECONNABORTED') {
|
if (err.code === 'ECONNABORTED') {
|
||||||
message.warn('请求超时');
|
message.warn(i18n.t('requestTimeout'));
|
||||||
return Promise.resolve(err);
|
return Promise.resolve(err);
|
||||||
}
|
}
|
||||||
let res = err.response;
|
let res = err.response;
|
||||||
let data = res.data;
|
let data = res.data;
|
||||||
if (data.hasOwnProperty('code')) {
|
if (data.hasOwnProperty('code')) {
|
||||||
if (data.code !== 0){
|
if (data.code !== 0){
|
||||||
message.warn(data.msg);
|
message.warn(translate(data.msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return Promise.resolve(res);
|
||||||
@@ -47,10 +45,7 @@ ReactDOM.render(
|
|||||||
<Router>
|
<Router>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<Wrapper><Overview/></Wrapper>}/>
|
<Route path="/" element={<Wrapper><Overview/></Wrapper>}/>
|
||||||
<Route
|
<Route path="*" element={<Err/>}/>
|
||||||
path="*"
|
|
||||||
element={<Err/>}
|
|
||||||
/>
|
|
||||||
</Routes>
|
</Routes>
|
||||||
</Router>,
|
</Router>,
|
||||||
document.getElementById('root')
|
document.getElementById('root')
|
||||||
|
73
web/src/locale/en.json
Normal file
73
web/src/locale/en.json
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
{
|
||||||
|
"requestTimeout": "Request timeout",
|
||||||
|
"pageNotFound": "Page Not Found",
|
||||||
|
"unknownError": "Unknown error",
|
||||||
|
"invalidParameter": "Invalid parameter",
|
||||||
|
|
||||||
|
"hostname": "Hostname",
|
||||||
|
"username": "Username",
|
||||||
|
"cpuUsage": "CPU Usage",
|
||||||
|
"memUsage": "Mem Usage",
|
||||||
|
"diskUsage": "Disk Usage",
|
||||||
|
"memTotal": "Memory",
|
||||||
|
"os": "OS",
|
||||||
|
"arch": "Arch",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"netStat": "Network IO",
|
||||||
|
"operations": "Operations",
|
||||||
|
"hours": "h",
|
||||||
|
"minutes": "m",
|
||||||
|
"terminal": "Terminal",
|
||||||
|
"procMgr": "ProcMgr",
|
||||||
|
"fileMgr": "Explorer",
|
||||||
|
"screenshot": "Screenshot",
|
||||||
|
"lock": "Lock",
|
||||||
|
"logoff": "Logoff",
|
||||||
|
"hibernate": "Hibernate",
|
||||||
|
"suspend": "Suspend",
|
||||||
|
"restart": "Restart",
|
||||||
|
"shutdown": "Shutdown",
|
||||||
|
"offline": "Offline",
|
||||||
|
"generate": "Generate client",
|
||||||
|
"requestFailed": "Request failed",
|
||||||
|
"operationConfirm": "Are you sure to {0} this device?",
|
||||||
|
"operationSuccess": "Operation executed",
|
||||||
|
|
||||||
|
"fileExplorer": "File Explorer",
|
||||||
|
"fileName": "Name",
|
||||||
|
"fileSize": "Size",
|
||||||
|
"modifyTime": "Modify Time",
|
||||||
|
"file": "file",
|
||||||
|
"folder": "folder",
|
||||||
|
"delete": "Delete",
|
||||||
|
"download": "Download",
|
||||||
|
"deleteConfirm": "Are you sure to delete this {0}?",
|
||||||
|
"deleteSuccess": "File or folder deleted",
|
||||||
|
"dateTimeFormat": "MMM D, YYYY h:mm A",
|
||||||
|
|
||||||
|
"host": "Host",
|
||||||
|
"port": "Port",
|
||||||
|
"path": "Path",
|
||||||
|
"osArch": "OS / Arch",
|
||||||
|
|
||||||
|
"processManager": "Process Manager",
|
||||||
|
"procName": "Process",
|
||||||
|
"killProc": "Kill",
|
||||||
|
"confirmKillProc": "Are you sure to kill this process?",
|
||||||
|
"killProcSuccess": "Process killed",
|
||||||
|
|
||||||
|
"reconnecting": "Reconnecting...",
|
||||||
|
"disconnected": "Session disconnected",
|
||||||
|
|
||||||
|
"terminalSessionCreationFailed": "Failed to create terminal session",
|
||||||
|
"deviceNotExists": "Device not exists or not online",
|
||||||
|
"responseTimeout": "Response timeout",
|
||||||
|
"terminalSessionClosed": "Terminal session closed",
|
||||||
|
"osOrArchNotPrebuilt": "The OS or Arch is not prebuilt",
|
||||||
|
"configGenerateFailed": "Failed to generate client config",
|
||||||
|
"tooLargeConfig": "Config is too large",
|
||||||
|
"fileUploadFailed": "Failed to upload file",
|
||||||
|
"screenshotFailed": "Failed to take screenshot",
|
||||||
|
"screenshotObtainFailed": "Failed to obtain screenshot",
|
||||||
|
"invalidFileRange": "Invalid file range"
|
||||||
|
}
|
29
web/src/locale/locale.js
Normal file
29
web/src/locale/locale.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import i18n from 'i18next';
|
||||||
|
|
||||||
|
const locales = {
|
||||||
|
'en': 'en',
|
||||||
|
'en-US': 'en',
|
||||||
|
'zh-CN': 'zh-CN',
|
||||||
|
};
|
||||||
|
const lang = navigator.language && navigator.language.length ? navigator.language : 'en';
|
||||||
|
|
||||||
|
let resources = {};
|
||||||
|
for (const locale in locales) {
|
||||||
|
resources[locale] = {
|
||||||
|
translation: require(`./${locales[locale]}.json`),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
i18n.init({
|
||||||
|
lng: lang,
|
||||||
|
fallbackLng: 'en',
|
||||||
|
initImmediate: false,
|
||||||
|
resources
|
||||||
|
});
|
||||||
|
|
||||||
|
function getLang() {
|
||||||
|
return lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { getLang };
|
||||||
|
export default i18n;
|
73
web/src/locale/zh-CN.json
Normal file
73
web/src/locale/zh-CN.json
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
{
|
||||||
|
"requestTimeout": "请求超时",
|
||||||
|
"pageNotFound": "未找到该页面",
|
||||||
|
"unknownError": "未知错误",
|
||||||
|
"invalidParameter": "参数无效",
|
||||||
|
|
||||||
|
"hostname": "主机名",
|
||||||
|
"username": "用户名",
|
||||||
|
"cpuUsage": "CPU使用率",
|
||||||
|
"memUsage": "内存使用率",
|
||||||
|
"diskUsage": "磁盘使用率",
|
||||||
|
"memTotal": "内存大小",
|
||||||
|
"os": "操作系统",
|
||||||
|
"arch": "架构",
|
||||||
|
"uptime": "运行时间",
|
||||||
|
"netStat": "网络状态",
|
||||||
|
"operations": "操作",
|
||||||
|
"hours": "小时",
|
||||||
|
"minutes": "分钟",
|
||||||
|
"terminal": "终端",
|
||||||
|
"procMgr": "进程",
|
||||||
|
"fileMgr": "文件",
|
||||||
|
"screenshot": "截屏",
|
||||||
|
"lock": "锁屏",
|
||||||
|
"logoff": "注销",
|
||||||
|
"hibernate": "休眠",
|
||||||
|
"suspend": "睡眠",
|
||||||
|
"restart": "重启",
|
||||||
|
"shutdown": "关机",
|
||||||
|
"offline": "离线",
|
||||||
|
"generate": "生成客户端",
|
||||||
|
"requestFailed": "请求服务器失败",
|
||||||
|
"operationConfirm": "确定要{0}该设备吗?",
|
||||||
|
"operationSuccess": "操作已执行",
|
||||||
|
|
||||||
|
"fileExplorer": "文件管理器",
|
||||||
|
"fileName": "文件名",
|
||||||
|
"fileSize": "大小",
|
||||||
|
"modifyTime": "修改时间",
|
||||||
|
"file": "文件",
|
||||||
|
"folder": "文件夹",
|
||||||
|
"delete": "删除",
|
||||||
|
"download": "下载",
|
||||||
|
"deleteConfirm": "确定要删除该{0}吗?",
|
||||||
|
"deleteSuccess": "文件或目录已被删除",
|
||||||
|
"dateTimeFormat": "YYYY/MM/DD HH:mm",
|
||||||
|
|
||||||
|
"host": "主机",
|
||||||
|
"port": "端口",
|
||||||
|
"path": "路径",
|
||||||
|
"osArch": "操作系统/架构",
|
||||||
|
|
||||||
|
"processManager": "进程管理器",
|
||||||
|
"procName": "进程名",
|
||||||
|
"killProc": "结束",
|
||||||
|
"confirmKillProc": "确定要结束该进程吗?",
|
||||||
|
"killProcSuccess": "进程已结束",
|
||||||
|
|
||||||
|
"reconnecting": "正在重新连接...",
|
||||||
|
"disconnected": "连接已断开",
|
||||||
|
|
||||||
|
"terminalSessionCreationFailed": "终端会话创建失败",
|
||||||
|
"deviceNotExists": "设备不存在或已离线",
|
||||||
|
"responseTimeout": "响应超时",
|
||||||
|
"terminalSessionClosed": "终端会话已关闭",
|
||||||
|
"osOrArchNotPrebuilt": "该操作系统或架构的客户端未预编译",
|
||||||
|
"configGenerateFailed": "配置文件生成失败",
|
||||||
|
"tooLargeConfig": "配置文件过大",
|
||||||
|
"fileUploadFailed": "文件上传失败",
|
||||||
|
"screenshotFailed": "截屏失败",
|
||||||
|
"screenshotObtainFailed": "截屏读取失败",
|
||||||
|
"invalidFileRange": "文件范围错误"
|
||||||
|
}
|
@@ -1,4 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import i18n from "../locale/locale";
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
// setTimeout(()=>{
|
// setTimeout(()=>{
|
||||||
@@ -7,9 +8,7 @@ export default function () {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<h1 style={{textAlign: 'center', userSelect: 'none'}}>
|
<h1 style={{textAlign: 'center', userSelect: 'none'}}>
|
||||||
Page Not Found.
|
{i18n.t('pageNotFound')}
|
||||||
<br/>
|
|
||||||
未找到该页面。
|
|
||||||
</h1>
|
</h1>
|
||||||
);
|
);
|
||||||
}
|
}
|
@@ -1,12 +1,13 @@
|
|||||||
import React, {useEffect, useRef, useState} from 'react';
|
import React, {useEffect, useRef, useState} from 'react';
|
||||||
import ProTable, {TableDropdown} from '@ant-design/pro-table';
|
import ProTable, {TableDropdown} from '@ant-design/pro-table';
|
||||||
import {Button, Image, message, Modal, Progress} from 'antd';
|
import {Button, Image, message, Modal, Progress} from 'antd';
|
||||||
import {formatSize, request, tsToTime, waitTime} from "../utils/utils";
|
import {formatSize, request, translate, tsToTime, waitTime} from "../utils/utils";
|
||||||
import Terminal from "../components/terminal";
|
import Terminal from "../components/terminal";
|
||||||
import Processes from "../components/processes";
|
import Processes from "../components/processes";
|
||||||
import Generate from "../components/generate";
|
import Generate from "../components/generate";
|
||||||
import Browser from "../components/browser";
|
import Explorer from "../components/explorer";
|
||||||
import {QuestionCircleOutlined} from "@ant-design/icons";
|
import {QuestionCircleOutlined} from "@ant-design/icons";
|
||||||
|
import i18n from "../locale/locale";
|
||||||
|
|
||||||
import defaultColumnsState from "../config/columnsState.json";
|
import defaultColumnsState from "../config/columnsState.json";
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ console.log("%c By XZB %c https://github.com/XZB-1248/Spark", 'font-family:"Helv
|
|||||||
|
|
||||||
function overview(props) {
|
function overview(props) {
|
||||||
const [procMgr, setProcMgr] = useState(false);
|
const [procMgr, setProcMgr] = useState(false);
|
||||||
const [browser, setBrowser] = useState(false);
|
const [explorer, setExplorer] = useState(false);
|
||||||
const [generate, setGenerate] = useState(false);
|
const [generate, setGenerate] = useState(false);
|
||||||
const [terminal, setTerminal] = useState(false);
|
const [terminal, setTerminal] = useState(false);
|
||||||
const [screenBlob, setScreenBlob] = useState('');
|
const [screenBlob, setScreenBlob] = useState('');
|
||||||
@@ -26,14 +27,14 @@ function overview(props) {
|
|||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
key: 'hostname',
|
key: 'hostname',
|
||||||
title: 'Hostname',
|
title: i18n.t('hostname'),
|
||||||
dataIndex: 'hostname',
|
dataIndex: 'hostname',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 100
|
width: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'username',
|
key: 'username',
|
||||||
title: 'Username',
|
title: i18n.t('username'),
|
||||||
dataIndex: 'username',
|
dataIndex: 'username',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 90
|
width: 90
|
||||||
@@ -48,7 +49,7 @@ function overview(props) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'cpu_usage',
|
key: 'cpu_usage',
|
||||||
title: 'CPU Usage',
|
title: i18n.t('cpuUsage'),
|
||||||
dataIndex: 'cpu_usage',
|
dataIndex: 'cpu_usage',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (_, v) => <Progress percent={v.cpu_usage} showInfo={false} strokeWidth={12} trailColor='#FFECFF'/>,
|
render: (_, v) => <Progress percent={v.cpu_usage} showInfo={false} strokeWidth={12} trailColor='#FFECFF'/>,
|
||||||
@@ -56,7 +57,7 @@ function overview(props) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'mem_usage',
|
key: 'mem_usage',
|
||||||
title: 'Mem Usage',
|
title: i18n.t('memUsage'),
|
||||||
dataIndex: 'mem_usage',
|
dataIndex: 'mem_usage',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (_, v) => <Progress percent={v.mem_usage} showInfo={false} strokeWidth={12} trailColor='#FFECFF'/>,
|
render: (_, v) => <Progress percent={v.mem_usage} showInfo={false} strokeWidth={12} trailColor='#FFECFF'/>,
|
||||||
@@ -64,7 +65,7 @@ function overview(props) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'disk_usage',
|
key: 'disk_usage',
|
||||||
title: 'Disk Usage',
|
title: i18n.t('diskUsage'),
|
||||||
dataIndex: 'disk_usage',
|
dataIndex: 'disk_usage',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (_, v) => <Progress percent={v.disk_usage} showInfo={false} strokeWidth={12} trailColor='#FFECFF'/>,
|
render: (_, v) => <Progress percent={v.disk_usage} showInfo={false} strokeWidth={12} trailColor='#FFECFF'/>,
|
||||||
@@ -72,7 +73,7 @@ function overview(props) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'mem_total',
|
key: 'mem_total',
|
||||||
title: 'Mem',
|
title: i18n.t('memTotal'),
|
||||||
dataIndex: 'mem_total',
|
dataIndex: 'mem_total',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
renderText: formatSize,
|
renderText: formatSize,
|
||||||
@@ -80,14 +81,14 @@ function overview(props) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'os',
|
key: 'os',
|
||||||
title: 'OS',
|
title: i18n.t('os'),
|
||||||
dataIndex: 'os',
|
dataIndex: 'os',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 80
|
width: 80
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'arch',
|
key: 'arch',
|
||||||
title: 'Arch',
|
title: i18n.t('arch'),
|
||||||
dataIndex: 'arch',
|
dataIndex: 'arch',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 70
|
width: 70
|
||||||
@@ -115,7 +116,7 @@ function overview(props) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'uptime',
|
key: 'uptime',
|
||||||
title: 'Uptime',
|
title: i18n.t('uptime'),
|
||||||
dataIndex: 'uptime',
|
dataIndex: 'uptime',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
renderText: tsToTime,
|
renderText: tsToTime,
|
||||||
@@ -123,17 +124,17 @@ function overview(props) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'net_stat',
|
key: 'net_stat',
|
||||||
title: 'Network IO',
|
title: i18n.t('netStat'),
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
renderText: (_, v) => renderNetworkIO(v),
|
renderText: (_, v) => renderNetworkIO(v),
|
||||||
width: 170
|
width: 170
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'option',
|
key: 'option',
|
||||||
title: '操作',
|
title: i18n.t('operations'),
|
||||||
dataIndex: 'id',
|
dataIndex: 'id',
|
||||||
valueType: 'option',
|
valueType: 'option',
|
||||||
ellipsis: true,
|
ellipsis: false,
|
||||||
render: (_, device) => renderOperation(device),
|
render: (_, device) => renderOperation(device),
|
||||||
width: 170
|
width: 170
|
||||||
},
|
},
|
||||||
@@ -147,13 +148,13 @@ function overview(props) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Auto update is only available when all modal are closed.
|
// Auto update is only available when all modal are closed.
|
||||||
if (!procMgr && !browser && !generate && !terminal) {
|
if (!procMgr && !explorer && !generate && !terminal) {
|
||||||
let id = setInterval(getData, 3000);
|
let id = setInterval(getData, 3000);
|
||||||
return () => {
|
return () => {
|
||||||
clearInterval(id);
|
clearInterval(id);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}, [procMgr, browser, generate, terminal]);
|
}, [procMgr, explorer, generate, terminal]);
|
||||||
|
|
||||||
function getInitColumnsState() {
|
function getInitColumnsState() {
|
||||||
let data = localStorage.getItem(`columnsState`);
|
let data = localStorage.getItem(`columnsState`);
|
||||||
@@ -193,24 +194,24 @@ function overview(props) {
|
|||||||
|
|
||||||
function renderOperation(device) {
|
function renderOperation(device) {
|
||||||
return [
|
return [
|
||||||
<a key='terminal' onClick={setTerminal.bind(null, device.id)}>终端</a>,
|
<a key='terminal' onClick={setTerminal.bind(null, device.id)}>{i18n.t('terminal')}</a>,
|
||||||
<a key='procmgr' onClick={setProcMgr.bind(null, device.id)}>进程</a>,
|
<a key='procmgr' onClick={setProcMgr.bind(null, device.id)}>{i18n.t('procMgr')}</a>,
|
||||||
<a key='browser' onClick={() => {
|
<a key='explorer' onClick={() => {
|
||||||
setBrowser(device.id);
|
setExplorer(device.id);
|
||||||
setIsWindows(device.os === 'windows');
|
setIsWindows(device.os === 'windows');
|
||||||
}}>文件</a>,
|
}}>{i18n.t('fileMgr')}</a>,
|
||||||
<TableDropdown
|
<TableDropdown
|
||||||
key='more'
|
key='more'
|
||||||
onSelect={(key) => callDevice(key, device.id)}
|
onSelect={(key) => callDevice(key, device.id)}
|
||||||
menus={[
|
menus={[
|
||||||
{key: 'screenshot', name: '截屏'},
|
{key: 'screenshot', name: i18n.t('screenshot')},
|
||||||
{key: 'lock', name: '锁屏'},
|
{key: 'lock', name: i18n.t('lock')},
|
||||||
{key: 'logoff', name: '注销'},
|
{key: 'logoff', name: i18n.t('logoff')},
|
||||||
{key: 'hibernate', name: '休眠'},
|
{key: 'hibernate', name: i18n.t('hibernate')},
|
||||||
{key: 'suspend', name: '睡眠'},
|
{key: 'suspend', name: i18n.t('suspend')},
|
||||||
{key: 'restart', name: '重启'},
|
{key: 'restart', name: i18n.t('restart')},
|
||||||
{key: 'shutdown', name: '关机'},
|
{key: 'shutdown', name: i18n.t('shutdown')},
|
||||||
{key: 'offline', name: '离线'},
|
{key: 'offline', name: i18n.t('offline')},
|
||||||
]}
|
]}
|
||||||
/>,
|
/>,
|
||||||
]
|
]
|
||||||
@@ -228,7 +229,7 @@ function overview(props) {
|
|||||||
data = JSON.parse(str);
|
data = JSON.parse(str);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
}
|
}
|
||||||
message.warn(data.msg ?? '请求服务器失败')
|
message.warn(data.msg ? translate(data.msg) : i18n.t('requestFailed'));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (screenBlob.length > 0) {
|
if (screenBlob.length > 0) {
|
||||||
@@ -239,28 +240,14 @@ function overview(props) {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let menus = {
|
|
||||||
lock: '锁屏',
|
|
||||||
logoff: '注销',
|
|
||||||
hibernate: '休眠',
|
|
||||||
suspend: '睡眠',
|
|
||||||
restart: '重启',
|
|
||||||
shutdown: '关机',
|
|
||||||
offline: '离线',
|
|
||||||
};
|
|
||||||
if (!menus.hasOwnProperty(act)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: `确定要${menus[act]}该设备吗?`,
|
title: i18n.t('operationConfirm').replace('{0}', i18n.t(act).toUpperCase()),
|
||||||
icon: <QuestionCircleOutlined/>,
|
icon: <QuestionCircleOutlined/>,
|
||||||
okText: '确定',
|
|
||||||
cancelText: '取消',
|
|
||||||
onOk() {
|
onOk() {
|
||||||
request('/api/device/' + act, {device: device}).then(res => {
|
request('/api/device/' + act, {device: device}).then(res => {
|
||||||
let data = res.data;
|
let data = res.data;
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
message.success('操作已执行');
|
message.success(i18n.t('operationSuccess'));
|
||||||
tableRef.current.reload();
|
tableRef.current.reload();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -270,7 +257,7 @@ function overview(props) {
|
|||||||
|
|
||||||
function toolBar() {
|
function toolBar() {
|
||||||
return (
|
return (
|
||||||
<Button type='primary' onClick={setGenerate.bind(null, true)}>生成客户端</Button>
|
<Button type='primary' onClick={setGenerate.bind(null, true)}>{i18n.t('generate')}</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,11 +323,11 @@ function overview(props) {
|
|||||||
visible={generate}
|
visible={generate}
|
||||||
onVisibleChange={setGenerate}
|
onVisibleChange={setGenerate}
|
||||||
/>
|
/>
|
||||||
<Browser
|
<Explorer
|
||||||
isWindows={isWindows}
|
isWindows={isWindows}
|
||||||
visible={browser}
|
visible={explorer}
|
||||||
device={browser}
|
device={explorer}
|
||||||
onCancel={setBrowser.bind(null, false)}
|
onCancel={setExplorer.bind(null, false)}
|
||||||
/>
|
/>
|
||||||
<Processes
|
<Processes
|
||||||
visible={procMgr}
|
visible={procMgr}
|
||||||
@@ -353,6 +340,10 @@ function overview(props) {
|
|||||||
onCancel={setTerminal.bind(null, false)}
|
onCancel={setTerminal.bind(null, false)}
|
||||||
/>
|
/>
|
||||||
<ProTable
|
<ProTable
|
||||||
|
scroll={{
|
||||||
|
x: 'max-content',
|
||||||
|
scrollToFirstRowOnChange: true
|
||||||
|
}}
|
||||||
rowKey='id'
|
rowKey='id'
|
||||||
search={false}
|
search={false}
|
||||||
options={options}
|
options={options}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import Qs from 'qs';
|
import Qs from 'qs';
|
||||||
|
import i18n from "../locale/locale";
|
||||||
|
|
||||||
function request(url, data, headers, ext, noTrans) {
|
function request(url, data, headers, ext, noTrans) {
|
||||||
let _headers = headers ?? {};
|
let _headers = headers ?? {};
|
||||||
@@ -35,7 +36,7 @@ function tsToTime(ts) {
|
|||||||
let hours = Math.floor(ts / 3600);
|
let hours = Math.floor(ts / 3600);
|
||||||
ts %= 3600;
|
ts %= 3600;
|
||||||
let minutes = Math.floor(ts / 60);
|
let minutes = Math.floor(ts / 60);
|
||||||
return `${hours}小时${minutes}分钟`;
|
return `${String(hours) + i18n.t('hours') + String(minutes) + i18n.t('minutes')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function post(url, data, ext) {
|
function post(url, data, ext) {
|
||||||
@@ -58,4 +59,10 @@ function post(url, data, ext) {
|
|||||||
form.remove();
|
form.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
export {post, request, waitTime, formatSize, tsToTime};
|
function translate(text) {
|
||||||
|
return text.replace(/\$\{i18n\|([a-zA-Z0-9]+)\}/g, (match, key) => {
|
||||||
|
return i18n.t(key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {post, request, waitTime, formatSize, tsToTime, translate};
|
Reference in New Issue
Block a user