GUI热更配置
This commit is contained in:
parent
149932a66c
commit
f3c3c517bf
@ -4,5 +4,5 @@ Website = "http://legu.cc"
|
|||||||
Icon = "app.png"
|
Icon = "app.png"
|
||||||
Name = "RobotGUI"
|
Name = "RobotGUI"
|
||||||
ID = "cc.legu.app"
|
ID = "cc.legu.app"
|
||||||
Version = "1.0.9"
|
Version = "1.0.11"
|
||||||
Build = 10
|
Build = 14
|
||||||
|
@ -92,7 +92,7 @@ const (
|
|||||||
TOOLBAR_GEN = "Luban"
|
TOOLBAR_GEN = "Luban"
|
||||||
TOOLBAR_SEC = "密码器"
|
TOOLBAR_SEC = "密码器"
|
||||||
TOOLBAR_WEL = "欢迎"
|
TOOLBAR_WEL = "欢迎"
|
||||||
TOOLBAR_TERM = "终端"
|
TOOLBAR_TERM = "同步配置"
|
||||||
TOOLBAR_PB = "protobuf"
|
TOOLBAR_PB = "protobuf"
|
||||||
|
|
||||||
//monitor
|
//monitor
|
||||||
|
@ -5,5 +5,12 @@ type SSHModel struct {
|
|||||||
Port string
|
Port string
|
||||||
UserName string
|
UserName string
|
||||||
Password string
|
Password string
|
||||||
CmdLast string
|
LocalDir string
|
||||||
|
RemoteDir string
|
||||||
|
/////
|
||||||
|
ServerIp string
|
||||||
|
WorkDir string
|
||||||
|
LubanCli string
|
||||||
|
DataDir string
|
||||||
|
JsonDir string
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
upgradeUrl: http://10.0.0.9:8080/
|
upgradeUrl: http://10.0.0.9:8080/
|
||||||
services:
|
services:
|
||||||
- service:
|
- service:
|
||||||
sid: 1
|
sid: "df01"
|
||||||
name: 外网
|
name: 外网
|
||||||
url: ws://119.3.89.14:7891/gateway
|
url: ws://119.3.89.14:9891/gateway
|
||||||
- service:
|
- service:
|
||||||
sid: "dfz"
|
sid: "dfz"
|
||||||
name: 赵长远
|
name: 赵长远
|
||||||
|
@ -7,16 +7,28 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/pkg/sftp"
|
"github.com/pkg/sftp"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var sftpCli *sftp.Client
|
||||||
|
var sftpOne sync.Once
|
||||||
|
|
||||||
type SSHService struct {
|
type SSHService struct {
|
||||||
Client *ssh.Client
|
Client *ssh.Client
|
||||||
LastResult string
|
LastResult string //执行结果
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSSHService() *SSHService {
|
||||||
|
ss := &SSHService{}
|
||||||
|
return ss
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *SSHService) Connect(user, password, host, key string, port int, cipherList []string) error {
|
func (ss *SSHService) Connect(user, password, host, key string, port int, cipherList []string) error {
|
||||||
@ -79,9 +91,36 @@ func (ss *SSHService) Connect(user, password, host, key string, port int, cipher
|
|||||||
if ss.Client, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
|
if ss.Client, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sftpCli, err = sftp.NewClient(ss.Client)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ss *SSHService) getSftp() (*sftp.Client, error) {
|
||||||
|
if ss.Client == nil {
|
||||||
|
return nil, errors.New("ssh client is nil")
|
||||||
|
}
|
||||||
|
sftpOne.Do(func() {
|
||||||
|
if sftpCli, err = sftp.NewClient(ss.Client); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return sftpCli, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ss *SSHService) Close() {
|
||||||
|
if ss.Client != nil {
|
||||||
|
if err := ss.Client.Close(); err != nil {
|
||||||
|
logrus.WithField("err", err).Error("close ssh err")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if sftpCli != nil {
|
||||||
|
// if err := sftpCli.Close(); err != nil {
|
||||||
|
// logrus.WithField("err", err).Error("close sftp err")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
func (ss *SSHService) RunShell(shell string) {
|
func (ss *SSHService) RunShell(shell string) {
|
||||||
var (
|
var (
|
||||||
session *ssh.Session
|
session *ssh.Session
|
||||||
@ -109,7 +148,6 @@ func (ss *SSHService) RunShell(shell string) {
|
|||||||
} else {
|
} else {
|
||||||
ss.LastResult = string(output)
|
ss.LastResult = string(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//单个copy
|
//单个copy
|
||||||
@ -117,11 +155,21 @@ func (ss *SSHService) ScpCopy(localFilePath, remoteDir string) error {
|
|||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
sftpClient, err := sftp.NewClient(ss.Client)
|
|
||||||
|
fi, err := os.Stat(localFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if fi.IsDir() {
|
||||||
|
return errors.New(localFilePath + " is not file")
|
||||||
|
}
|
||||||
|
|
||||||
|
sftpCli, err = ss.getSftp()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("new sftp client error: %w", err)
|
return fmt.Errorf("new sftp client error: %w", err)
|
||||||
}
|
}
|
||||||
defer sftpClient.Close()
|
|
||||||
|
// defer sftpCli.Close()
|
||||||
|
|
||||||
srcFile, err := os.Open(localFilePath)
|
srcFile, err := os.Open(localFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -130,8 +178,15 @@ func (ss *SSHService) ScpCopy(localFilePath, remoteDir string) error {
|
|||||||
}
|
}
|
||||||
defer srcFile.Close()
|
defer srcFile.Close()
|
||||||
|
|
||||||
var remoteFileName = path.Base(localFilePath)
|
var remoteFileName string
|
||||||
dstFile, err := sftpClient.Create(path.Join(remoteDir, remoteFileName))
|
sysTyep := runtime.GOOS
|
||||||
|
if sysTyep == "windows" {
|
||||||
|
remoteFileName = path.Base(filepath.ToSlash(localFilePath))
|
||||||
|
} else {
|
||||||
|
remoteFileName = path.Base(localFilePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
dstFile, err := sftpCli.Create(path.Join(remoteDir, remoteFileName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("scpCopy:", err)
|
log.Println("scpCopy:", err)
|
||||||
return err
|
return err
|
||||||
@ -143,10 +198,48 @@ func (ss *SSHService) ScpCopy(localFilePath, remoteDir string) error {
|
|||||||
return fmt.Errorf("read local file failed: %w", err)
|
return fmt.Errorf("read local file failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dstFile.Write(fileByte)
|
if _, err := dstFile.Write(fileByte); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//批量copy
|
||||||
|
func (ss *SSHService) BatchScpCoy(cfs []CopyFiles, remoteDir string) error {
|
||||||
|
sftpCli, err = ss.getSftp()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("new sftp client error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range cfs {
|
||||||
|
srcFile, err := os.Open(path.Join(f.Dir, f.FileName))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer srcFile.Close()
|
||||||
|
|
||||||
|
dstFile, err := sftpCli.Create(path.Join(remoteDir, f.FileName))
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error("scpCopy:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer dstFile.Close()
|
||||||
|
|
||||||
|
fileByte, err := ioutil.ReadAll(srcFile)
|
||||||
|
if nil != err {
|
||||||
|
return fmt.Errorf("read local file failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := dstFile.Write(fileByte); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Deprecated Scp
|
||||||
func (ss *SSHService) Scp(targetDir, srcFileName string) (int, error) {
|
func (ss *SSHService) Scp(targetDir, srcFileName string) (int, error) {
|
||||||
sftpClient, err := sftp.NewClient(ss.Client)
|
sftpClient, err := sftp.NewClient(ss.Client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -187,3 +280,8 @@ func (ss *SSHService) Scp(targetDir, srcFileName string) (int, error) {
|
|||||||
}
|
}
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CopyFiles struct {
|
||||||
|
Dir string
|
||||||
|
FileName string
|
||||||
|
}
|
||||||
|
@ -2,6 +2,8 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -36,9 +38,21 @@ func TestScp(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
path := filepath.Join(`E:/svn/dreamworks/client/dreamworks/ExcelFile/JSON/`, "game_vikingchallenge.json")
|
||||||
if err := ssh.ScpCopy(`E:/svn/dreamworks/client/dreamworks/ExcelFile/testscp.txt`, "/opt"); err != nil {
|
fmt.Println(path)
|
||||||
|
if err := ssh.ScpCopy(path, "/opt/json/"); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPath(t *testing.T) {
|
||||||
|
Dir := `E:/svn/dreamworks/client/dreamworks/ExcelFile/JSON/`
|
||||||
|
mypath := filepath.Join(Dir, "a.json")
|
||||||
|
s := filepath.ToSlash(mypath)
|
||||||
|
fmt.Println(path.Base(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMath(t *testing.T) {
|
||||||
|
a := float64(10) / float64(3)
|
||||||
|
fmt.Println(a)
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,6 @@ func (this *appGen) LazyInit(obs observer.Observer) error {
|
|||||||
this.goList.itemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
|
this.goList.itemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
|
||||||
}
|
}
|
||||||
this.goList.changeFileCount()
|
this.goList.changeFileCount()
|
||||||
// this.goList.titleLabel.SetText(fmt.Sprintf("(%d/%d)", len(this.goList.selItemIds), this.goList.fileTotal))
|
|
||||||
this.goList.itemList.Refresh()
|
this.goList.itemList.Refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +207,8 @@ func (this *appGen) LazyInit(obs observer.Observer) error {
|
|||||||
this.goList.selItemIds = append(this.goList.selItemIds, v.Text)
|
this.goList.selItemIds = append(this.goList.selItemIds, v.Text)
|
||||||
this.goList.itemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
|
this.goList.itemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
|
||||||
}
|
}
|
||||||
this.goList.titleLabel.SetText(fmt.Sprintf("(%d/%d)", len(this.goList.selItemIds), this.goList.fileTotal))
|
this.goList.changeFileCount()
|
||||||
|
// this.goList.titleLabel.SetText(fmt.Sprintf("(%d/%d)", len(this.goList.selItemIds), this.goList.fileTotal))
|
||||||
this.goList.itemList.Refresh()
|
this.goList.itemList.Refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,7 +257,6 @@ func (this *appGen) LazyInit(obs observer.Observer) error {
|
|||||||
list.itemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
|
list.itemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
|
||||||
}
|
}
|
||||||
this.jsonList.changeFileCount()
|
this.jsonList.changeFileCount()
|
||||||
// list.titleLabel.SetText(fmt.Sprintf("(%d/%d)", len(list.selItemIds), list.fileTotal))
|
|
||||||
list.itemList.Refresh()
|
list.itemList.Refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,6 +406,12 @@ func NewFileList() *fileList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *fileList) reset() {
|
||||||
|
f.fileTotal = 0
|
||||||
|
f.selItemIds = []string{}
|
||||||
|
f.cachedList = NewList("")
|
||||||
|
}
|
||||||
|
|
||||||
func (f *fileList) createList() *widget.List {
|
func (f *fileList) createList() *widget.List {
|
||||||
f.itemList = widget.NewList(
|
f.itemList = widget.NewList(
|
||||||
func() int {
|
func() int {
|
||||||
@ -464,6 +469,24 @@ func (f *fileList) deleteItem(name string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *fileList) loadItem(dirPath string) {
|
||||||
|
f.reset()
|
||||||
|
files, err := ioutil.ReadDir(dirPath)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
if !file.IsDir() {
|
||||||
|
f.addItem(file.Name())
|
||||||
|
f.selItemIds = append(f.selItemIds, file.Name())
|
||||||
|
f.fileTotal++
|
||||||
|
logrus.Debugf("%v", file.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 改变列表项目
|
// 改变列表项目
|
||||||
func (f *fileList) changeItem(tmpDir, projectDir string) {
|
func (f *fileList) changeItem(tmpDir, projectDir string) {
|
||||||
f.fileTotal = 0
|
f.fileTotal = 0
|
||||||
@ -514,6 +537,11 @@ func (f *fileList) changeFileCount() {
|
|||||||
f.titleLabel.SetText(fmt.Sprintf("(%d/%d)", len(f.selItemIds), f.fileTotal))
|
f.titleLabel.SetText(fmt.Sprintf("(%d/%d)", len(f.selItemIds), f.fileTotal))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CopyFiles struct {
|
||||||
|
Dir string
|
||||||
|
FileName string
|
||||||
|
}
|
||||||
|
|
||||||
func (a *appGen) GetAppName() string {
|
func (a *appGen) GetAppName() string {
|
||||||
return common.TOOLBAR_GEN
|
return common.TOOLBAR_GEN
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,21 @@ package ui
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"go_dreamfactory/cmd/v2/lib/common"
|
"go_dreamfactory/cmd/v2/lib/common"
|
||||||
"go_dreamfactory/cmd/v2/model"
|
"go_dreamfactory/cmd/v2/model"
|
||||||
"go_dreamfactory/cmd/v2/service"
|
"go_dreamfactory/cmd/v2/service"
|
||||||
"go_dreamfactory/cmd/v2/service/observer"
|
"go_dreamfactory/cmd/v2/service/observer"
|
||||||
|
"image/color"
|
||||||
|
"math/rand"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/canvas"
|
||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
"fyne.io/fyne/v2/dialog"
|
"fyne.io/fyne/v2/dialog"
|
||||||
"fyne.io/fyne/v2/layout"
|
"fyne.io/fyne/v2/layout"
|
||||||
@ -22,13 +31,26 @@ type appTerm struct {
|
|||||||
|
|
||||||
obs observer.Observer
|
obs observer.Observer
|
||||||
sshService *service.SSHService
|
sshService *service.SSHService
|
||||||
|
|
||||||
|
jsonList *fileList //json列表
|
||||||
|
cProgress *widget.ProgressBarInfinite //连接进度条进度条
|
||||||
|
upProgress *widget.ProgressBar //上传进度条
|
||||||
|
endProgress sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *appTerm) LazyInit(obs observer.Observer) error {
|
func (this *appTerm) LazyInit(obs observer.Observer) error {
|
||||||
this.obs = obs
|
this.obs = obs
|
||||||
this.sshService = &service.SSHService{}
|
this.sshService = &service.SSHService{}
|
||||||
|
this.jsonList = NewFileList()
|
||||||
|
|
||||||
this.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_TERM, theme.ContentCopyIcon(), nil)
|
//progress
|
||||||
|
this.cProgress = widget.NewProgressBarInfinite()
|
||||||
|
this.cProgress.Hide()
|
||||||
|
|
||||||
|
this.upProgress = widget.NewProgressBar()
|
||||||
|
this.upProgress.Hide()
|
||||||
|
|
||||||
|
this.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_TERM, theme.MailSendIcon(), nil)
|
||||||
content := container.NewMax()
|
content := container.NewMax()
|
||||||
content.Objects = []fyne.CanvasObject{}
|
content.Objects = []fyne.CanvasObject{}
|
||||||
|
|
||||||
@ -38,26 +60,15 @@ func (this *appTerm) LazyInit(obs observer.Observer) error {
|
|||||||
|
|
||||||
//left-top
|
//left-top
|
||||||
localDir := widget.NewEntry()
|
localDir := widget.NewEntry()
|
||||||
localDir.PlaceHolder = `本地目录`
|
localDir.PlaceHolder = `本地Json目录`
|
||||||
|
|
||||||
remoteDir := widget.NewEntry()
|
remoteDir := widget.NewEntry()
|
||||||
remoteDir.PlaceHolder = `远程目录`
|
remoteDir.PlaceHolder = `远程目录`
|
||||||
|
remoteDir.Text = "/home/liwei/go_dreamfactory/bin/json"
|
||||||
dirForm := widget.NewForm(
|
|
||||||
widget.NewFormItem("本地目录", container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
|
|
||||||
openFolder(localDir)
|
|
||||||
}), localDir)),
|
|
||||||
widget.NewFormItem("远程目录", container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
|
|
||||||
openFolder(remoteDir)
|
|
||||||
}), remoteDir)),
|
|
||||||
)
|
|
||||||
|
|
||||||
// output panel
|
|
||||||
output := widget.NewMultiLineEntry()
|
|
||||||
logrus.Debug(output.CursorRow)
|
|
||||||
|
|
||||||
//config
|
//config
|
||||||
ip := widget.NewEntry()
|
ip := widget.NewEntry()
|
||||||
|
ip.PlaceHolder = "10.0.0.9"
|
||||||
port := widget.NewEntry()
|
port := widget.NewEntry()
|
||||||
port.Text = "22" //default port
|
port.Text = "22" //default port
|
||||||
port.PlaceHolder = "端口"
|
port.PlaceHolder = "端口"
|
||||||
@ -67,40 +78,115 @@ func (this *appTerm) LazyInit(obs observer.Observer) error {
|
|||||||
password.PlaceHolder = "密码"
|
password.PlaceHolder = "密码"
|
||||||
|
|
||||||
passwordItem := &widget.FormItem{Text: "密码:", Widget: password}
|
passwordItem := &widget.FormItem{Text: "密码:", Widget: password}
|
||||||
|
|
||||||
|
configForm := widget.NewForm(
|
||||||
|
&widget.FormItem{Text: "IP:", Widget: container.NewBorder(nil, nil, nil, port, ip)},
|
||||||
|
&widget.FormItem{Text: "用户名:", Widget: userName},
|
||||||
|
passwordItem,
|
||||||
|
widget.NewFormItem("Json目录", container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
|
||||||
|
openFolder(localDir)
|
||||||
|
}), localDir)),
|
||||||
|
widget.NewFormItem("远程目录", remoteDir),
|
||||||
|
)
|
||||||
|
|
||||||
|
configForm.Items[4].HintText = "谨慎修改远程目录"
|
||||||
|
|
||||||
|
//svn form
|
||||||
|
lubanAddr := widget.NewEntry()
|
||||||
|
lubanAddr.PlaceHolder = "Luban服务IP"
|
||||||
|
|
||||||
|
workDir := widget.NewEntry()
|
||||||
|
workDir.PlaceHolder = "工作目录"
|
||||||
|
|
||||||
|
lubanCli := widget.NewEntry()
|
||||||
|
lubanCli.PlaceHolder = "luban客户端可执行文件"
|
||||||
|
|
||||||
|
//define
|
||||||
|
define := widget.NewEntry()
|
||||||
|
define.PlaceHolder = "定义文件"
|
||||||
|
define.Text = `Defines\\__root__.xml`
|
||||||
|
|
||||||
|
dataDir := widget.NewEntry()
|
||||||
|
dataDir.PlaceHolder = "Data目录"
|
||||||
|
|
||||||
|
jsonDir := widget.NewEntry()
|
||||||
|
jsonDir.PlaceHolder = "Json目录"
|
||||||
|
|
||||||
//set input entry
|
//set input entry
|
||||||
if sshConf != nil {
|
if sshConf != nil {
|
||||||
ip.Text = sshConf.Ip
|
ip.Text = sshConf.Ip
|
||||||
port.Text = sshConf.Port
|
port.Text = sshConf.Port
|
||||||
userName.Text = sshConf.UserName
|
userName.Text = sshConf.UserName
|
||||||
password.Text = sshConf.Password
|
password.Text = sshConf.Password
|
||||||
|
localDir.Text = sshConf.LocalDir
|
||||||
|
remoteDir.Text = sshConf.RemoteDir
|
||||||
|
// //
|
||||||
|
lubanAddr.Text = sshConf.ServerIp
|
||||||
|
workDir.Text = sshConf.WorkDir
|
||||||
|
lubanCli.Text = sshConf.LubanCli
|
||||||
|
dataDir.Text = sshConf.DataDir
|
||||||
|
jsonDir.Text = sshConf.JsonDir
|
||||||
}
|
}
|
||||||
|
|
||||||
configForm := widget.NewForm(
|
svnForm := widget.NewForm(
|
||||||
&widget.FormItem{Text: "IP:", Widget: container.NewBorder(nil, nil, nil, port, ip)},
|
&widget.FormItem{Text: "服务地址", Widget: lubanAddr},
|
||||||
&widget.FormItem{Text: "用户名:", Widget: userName},
|
&widget.FormItem{Text: "工作目录", Widget: container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
|
||||||
passwordItem,
|
openFolder(workDir)
|
||||||
|
}), workDir)},
|
||||||
|
&widget.FormItem{Text: "LubanCli", Widget: lubanCli},
|
||||||
|
&widget.FormItem{Text: "Data目录", Widget: dataDir},
|
||||||
|
&widget.FormItem{Text: "JSON目录", Widget: jsonDir},
|
||||||
)
|
)
|
||||||
|
|
||||||
// 非明文显示
|
// 非明文显示
|
||||||
passwordItem.Widget.Refresh()
|
passwordItem.Widget.Refresh()
|
||||||
|
|
||||||
// save func
|
// save func
|
||||||
saveBtn := widget.NewButtonWithIcon("保存配置", theme.DocumentSaveIcon(), func() {
|
saveFunc := func() {
|
||||||
if err := service.GetDbService().SaveSSHConf(&model.SSHModel{
|
if err := service.GetDbService().SaveSSHConf(&model.SSHModel{
|
||||||
Ip: ip.Text,
|
Ip: ip.Text,
|
||||||
UserName: userName.Text,
|
UserName: userName.Text,
|
||||||
Password: password.Text,
|
Password: password.Text,
|
||||||
Port: port.Text,
|
Port: port.Text,
|
||||||
|
LocalDir: localDir.Text,
|
||||||
|
RemoteDir: remoteDir.Text,
|
||||||
|
////
|
||||||
|
ServerIp: lubanAddr.Text,
|
||||||
|
WorkDir: workDir.Text,
|
||||||
|
LubanCli: lubanCli.Text,
|
||||||
|
DataDir: dataDir.Text,
|
||||||
|
JsonDir: jsonDir.Text,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
logrus.WithField("err", err).Debug("保存配置")
|
logrus.WithField("err", err).Debug("保存配置")
|
||||||
}
|
}
|
||||||
logrus.Debug("save term conf")
|
}
|
||||||
})
|
saveBtn1 := widget.NewButtonWithIcon("保存配置", theme.DocumentSaveIcon(), saveFunc)
|
||||||
|
|
||||||
|
saveBtn2 := widget.NewButtonWithIcon("保存配置", theme.DocumentSaveIcon(), saveFunc)
|
||||||
|
|
||||||
// conn func
|
// conn func
|
||||||
connBtn := &widget.Button{Text: "连接", Icon: theme.ConfirmIcon()}
|
connBtn := &widget.Button{Text: "连接", Icon: theme.MailForwardIcon()}
|
||||||
|
disConnBtn := &widget.Button{Text: "断开", Icon: theme.CancelIcon()}
|
||||||
|
syncBtn := &widget.Button{Text: "同步JSON", Icon: theme.ConfirmIcon()}
|
||||||
|
refreshBtn := &widget.Button{Text: "刷新", Icon: theme.ViewRefreshIcon()}
|
||||||
|
svnBtn := &widget.Button{Text: "SVN更新", Icon: theme.ConfirmIcon()}
|
||||||
|
explorBtn := &widget.Button{Text: "资源管理器", Icon: theme.FolderIcon()}
|
||||||
|
|
||||||
|
// 全选/全取消
|
||||||
|
allSelBtn := &widget.Button{Icon: theme.CheckButtonCheckedIcon()}
|
||||||
|
allCancelBtn := &widget.Button{Icon: theme.CheckButtonIcon()}
|
||||||
|
allSelBtn.Hide()
|
||||||
|
|
||||||
|
// 连接
|
||||||
connBtn.OnTapped = func() {
|
connBtn.OnTapped = func() {
|
||||||
|
this.cProgress.Show()
|
||||||
|
this.cProgress.Start()
|
||||||
ciphers := []string{}
|
ciphers := []string{}
|
||||||
|
|
||||||
|
if ip.Text == "" {
|
||||||
|
dialog.ShowError(errors.New("IP未填写"), toolWin.w)
|
||||||
|
return
|
||||||
|
}
|
||||||
if userName.Text == "" {
|
if userName.Text == "" {
|
||||||
dialog.ShowError(errors.New("账号未填写"), toolWin.w)
|
dialog.ShowError(errors.New("账号未填写"), toolWin.w)
|
||||||
return
|
return
|
||||||
@ -113,42 +199,230 @@ func (this *appTerm) LazyInit(obs observer.Observer) error {
|
|||||||
dialog.ShowError(errors.New("端口未填写"), toolWin.w)
|
dialog.ShowError(errors.New("端口未填写"), toolWin.w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if localDir.Text == "" {
|
||||||
|
dialog.ShowError(errors.New("JSON目录未填写"), toolWin.w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if remoteDir.Text == "" {
|
||||||
|
dialog.ShowError(errors.New("远程目录未填写"), toolWin.w)
|
||||||
|
return
|
||||||
|
}
|
||||||
connBtn.Disable()
|
connBtn.Disable()
|
||||||
|
|
||||||
err := this.sshService.Connect(userName.Text, password.Text, ip.Text, "", cast.ToInt(port.Text), ciphers)
|
err := this.sshService.Connect(userName.Text, password.Text, ip.Text, "", cast.ToInt(port.Text), ciphers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dialog.ShowError(err, toolWin.w)
|
dialog.ShowError(err, toolWin.w)
|
||||||
|
this.cProgress.Stop()
|
||||||
|
this.cProgress.Hide()
|
||||||
connBtn.Enable()
|
connBtn.Enable()
|
||||||
return
|
return
|
||||||
|
} else {
|
||||||
|
this.jsonList.loadItem(localDir.Text)
|
||||||
|
|
||||||
|
this.cProgress.Stop()
|
||||||
|
this.cProgress.Hide()
|
||||||
|
disConnBtn.Enable()
|
||||||
|
syncBtn.Enable()
|
||||||
|
this.upProgress.Hide()
|
||||||
|
allCancelBtn.Hide()
|
||||||
|
allSelBtn.Show()
|
||||||
|
refreshBtn.Enable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新JSON列表
|
||||||
|
refreshBtn.Disable()
|
||||||
|
refreshBtn.OnTapped = func() {
|
||||||
|
defer func() {
|
||||||
|
syncBtn.Enable()
|
||||||
|
allSelBtn.Show()
|
||||||
|
allCancelBtn.Hide()
|
||||||
|
}()
|
||||||
|
this.jsonList.loadItem(localDir.Text)
|
||||||
|
}
|
||||||
|
|
||||||
|
disConnBtn.Disable()
|
||||||
|
// 断开
|
||||||
|
disConnBtn.OnTapped = func() {
|
||||||
|
defer func() {
|
||||||
|
this.jsonList.reset()
|
||||||
|
connBtn.Enable()
|
||||||
|
disConnBtn.Disable()
|
||||||
|
syncBtn.Disable()
|
||||||
|
allSelBtn.Hide()
|
||||||
|
allCancelBtn.Show()
|
||||||
|
refreshBtn.Disable()
|
||||||
|
}()
|
||||||
|
this.sshService.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
//资源管理器
|
||||||
|
explorBtn.OnTapped = func() {
|
||||||
|
logrus.Debug(localDir.Text)
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
if err := exec.Command("explorer", filepath.Join(localDir.Text)).Start(); err != nil {
|
||||||
|
dialog.ShowError(err, toolWin.w)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//excute
|
}
|
||||||
excuteBtn := &widget.Button{Text: "执行", Icon: theme.ConfirmIcon()}
|
|
||||||
excuteBtn.TypedKey(&fyne.KeyEvent{Name: fyne.KeyEnter})
|
//使用说明
|
||||||
excuteBtn.OnTapped = func() {
|
helpBtn1 := widget.NewButtonWithIcon("", theme.QuestionIcon(), func() {
|
||||||
output.Text = ""
|
quesWin := fyne.CurrentApp().NewWindow("同步JSON使用说明")
|
||||||
excuteBtn.Disable()
|
quesWin.SetContent(widget.NewRichTextFromMarkdown(
|
||||||
|
`
|
||||||
|
* 同步Json的操作仅限于数值热更,非结构热更
|
||||||
|
* 将json文件热更到内网测试环境
|
||||||
|
* 提示:
|
||||||
|
* IP:10.0.0.9 22 (保持一致)
|
||||||
|
* 用户名:root(保持一致)
|
||||||
|
* 密码:(服务端同学提供)
|
||||||
|
* Json目录:(json文件目录全路径)
|
||||||
|
* 远程目录:/home/liwei/go_dreamfactory/bin/json/(保持一致)
|
||||||
|
* 全部填写完点击【保存配置】
|
||||||
|
* 点击【连接】,右侧面板选择要同步的文件
|
||||||
|
`))
|
||||||
|
quesWin.Resize(fyne.NewSize(350, 200))
|
||||||
|
quesWin.SetFixedSize(true)
|
||||||
|
quesWin.CenterOnScreen()
|
||||||
|
quesWin.Show()
|
||||||
|
})
|
||||||
|
|
||||||
|
helpBtn2 := widget.NewButtonWithIcon("", theme.QuestionIcon(), func() {
|
||||||
|
quesWin := fyne.CurrentApp().NewWindow("SVN更新使用说明")
|
||||||
|
c := widget.NewRichTextFromMarkdown(
|
||||||
|
`
|
||||||
|
* 基于Luban工具生成json
|
||||||
|
* 建议每次同步JSON之前先点击SVN更新
|
||||||
|
* 提示:
|
||||||
|
* 服务地址:10.0.1.11 (保持一致)
|
||||||
|
* 工作目录:svn下ExcelFile目录全路径
|
||||||
|
* LubanCli:Luban.Client\Luban.Client.exe (保持一致)
|
||||||
|
* Datas:Datas(保持一致)
|
||||||
|
* JSON目录:output\json(保持一致)
|
||||||
|
* 全部填写完点击【保存配置】
|
||||||
|
* 点击【SVN更新】生成json文件
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
quesWin.SetContent(c)
|
||||||
|
quesWin.Resize(fyne.NewSize(350, 200))
|
||||||
|
quesWin.SetFixedSize(true)
|
||||||
|
quesWin.CenterOnScreen()
|
||||||
|
quesWin.Show()
|
||||||
|
})
|
||||||
|
|
||||||
|
//同步JSON
|
||||||
|
syncBtn.Disable()
|
||||||
|
syncBtn.OnTapped = func() {
|
||||||
|
syncBtn.Disable()
|
||||||
defer func() {
|
defer func() {
|
||||||
excuteBtn.Enable()
|
syncBtn.Enable()
|
||||||
|
this.upProgress.Hide()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if this.sshService.Client == nil {
|
if this.sshService.Client == nil {
|
||||||
dialog.ShowError(errors.New("请先连接终端"), toolWin.w)
|
dialog.ShowError(errors.New("请先连接终端"), toolWin.w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
output.SetText(this.sshService.LastResult)
|
|
||||||
|
|
||||||
|
this.upProgress.Show()
|
||||||
|
this.upProgress.SetValue(0)
|
||||||
|
|
||||||
|
len := len(this.jsonList.selItemIds)
|
||||||
|
num := 0.0
|
||||||
|
|
||||||
|
increment := func(wg *sync.WaitGroup) {
|
||||||
|
num += float64(1) / float64(len)
|
||||||
|
this.upProgress.SetValue(num)
|
||||||
|
wg.Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
btns := container.NewHBox(excuteBtn, &layout.Spacer{}, saveBtn, connBtn)
|
for _, fileName := range this.jsonList.selItemIds {
|
||||||
|
this.endProgress.Add(1)
|
||||||
|
go func(fn string) {
|
||||||
|
time.Sleep(time.Second * time.Duration(rand.Intn(3)))
|
||||||
|
if err := this.sshService.ScpCopy(filepath.Join(localDir.Text, fn), remoteDir.Text); err != nil {
|
||||||
|
logrus.WithField("err", err).Error("同步json")
|
||||||
|
showTip(err.Error())
|
||||||
|
}
|
||||||
|
increment(&this.endProgress)
|
||||||
|
// 移除已上传的
|
||||||
|
this.jsonList.deleteItem(fn)
|
||||||
|
}(fileName)
|
||||||
|
}
|
||||||
|
this.endProgress.Wait()
|
||||||
|
this.upProgress.SetValue(1)
|
||||||
|
}
|
||||||
|
|
||||||
// layout
|
// SVN更新
|
||||||
split := container.NewVSplit(container.NewGridWithColumns(2,
|
svnBtn.OnTapped = func() {
|
||||||
dirForm,
|
this.cProgress.Show()
|
||||||
container.NewBorder(configForm, btns, widget.NewSeparator(), nil)), output)
|
this.cProgress.Start()
|
||||||
split.Offset = 0.25
|
svnBtn.Disable()
|
||||||
content.Objects = append(content.Objects, split)
|
defer func() {
|
||||||
|
this.cProgress.Hide()
|
||||||
|
this.cProgress.Stop()
|
||||||
|
svnBtn.Enable()
|
||||||
|
}()
|
||||||
|
commandStr := `%s -h %s -j cfg -- -d %s --input_data_dir %s --output_data_dir %s --gen_types data_json -s server`
|
||||||
|
arg := fmt.Sprintf(commandStr,
|
||||||
|
filepath.Join(workDir.Text, lubanCli.Text),
|
||||||
|
lubanAddr.Text,
|
||||||
|
filepath.Join(workDir.Text, define.Text),
|
||||||
|
filepath.Join(workDir.Text, dataDir.Text),
|
||||||
|
filepath.Join(workDir.Text, jsonDir.Text),
|
||||||
|
)
|
||||||
|
|
||||||
|
logrus.Debug(arg)
|
||||||
|
c := exec.Command("cmd.exe", "/c", arg)
|
||||||
|
if err := c.Run(); err != nil {
|
||||||
|
dialog.ShowError(err, toolWin.w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全部取消
|
||||||
|
allCancelBtn.OnTapped = func() {
|
||||||
|
defer func() {
|
||||||
|
allCancelBtn.Hide()
|
||||||
|
allSelBtn.Show()
|
||||||
|
}()
|
||||||
|
for i, v := range this.jsonList.cachedList.Items {
|
||||||
|
this.jsonList.cachedList.Items[i].Checked = true
|
||||||
|
this.jsonList.selItemIds = append(this.jsonList.selItemIds, v.Text)
|
||||||
|
this.jsonList.itemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
|
||||||
|
}
|
||||||
|
this.jsonList.itemList.Refresh()
|
||||||
|
}
|
||||||
|
// 全选
|
||||||
|
allSelBtn.OnTapped = func() {
|
||||||
|
defer func() {
|
||||||
|
allCancelBtn.Show()
|
||||||
|
allSelBtn.Hide()
|
||||||
|
}()
|
||||||
|
this.jsonList.selItemIds = []string{}
|
||||||
|
for i, v := range this.jsonList.cachedList.Items {
|
||||||
|
this.jsonList.cachedList.Items[i].Checked = false
|
||||||
|
this.jsonList.itemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
|
||||||
|
}
|
||||||
|
// this.jsonList.changeFileCount()
|
||||||
|
this.jsonList.itemList.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建json列表
|
||||||
|
this.jsonList.itemList = this.jsonList.createList()
|
||||||
|
|
||||||
|
btns1 := container.NewHBox(helpBtn1, &layout.Spacer{}, saveBtn1, connBtn, disConnBtn)
|
||||||
|
btns2 := container.NewHBox(helpBtn2, &layout.Spacer{}, saveBtn2, svnBtn)
|
||||||
|
|
||||||
|
split := container.NewHSplit(container.NewVBox(canvas.NewText("---只能在非上产环境!!!同步Json的操作仅限于数值热更,非结构热更---", color.RGBA{255, 0, 0, 255}), configForm,
|
||||||
|
btns1, svnForm, btns2, this.cProgress), container.NewBorder(container.NewHBox(allCancelBtn, allSelBtn, syncBtn, refreshBtn, explorBtn), nil, nil, nil, this.jsonList.itemList))
|
||||||
|
split.Offset = 0.45
|
||||||
|
content.Objects = append(content.Objects, container.NewBorder(nil, this.upProgress, nil, nil, split))
|
||||||
|
|
||||||
this.tabItem.Content = content
|
this.tabItem.Content = content
|
||||||
|
|
||||||
@ -167,7 +441,6 @@ func (a *appTerm) OnClose() bool {
|
|||||||
if a.sshService.Client != nil {
|
if a.sshService.Client != nil {
|
||||||
a.sshService.Client.Close()
|
a.sshService.Client.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
}, toolWin.w)
|
}, toolWin.w)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ func NewToolWindow(ui *UIImpl, parent fyne.Window) ToolWindow {
|
|||||||
openApp1(common.TOOLBAR_SEC)
|
openApp1(common.TOOLBAR_SEC)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
widget.NewToolbarAction(theme.ContentUndoIcon(), func() {
|
widget.NewToolbarAction(theme.MailSendIcon(), func() {
|
||||||
openApp1(common.TOOLBAR_TERM)
|
openApp1(common.TOOLBAR_TERM)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user