From f3c3c517bfaecb538c2e28bae58063d675d82cc0 Mon Sep 17 00:00:00 2001 From: wh_zcy Date: Wed, 28 Sep 2022 22:48:48 +0800 Subject: [PATCH] =?UTF-8?q?GUI=E7=83=AD=E6=9B=B4=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/v2/FyneApp.toml | 4 +- cmd/v2/lib/common/lang.go | 2 +- cmd/v2/model/ssh.go | 17 +- cmd/v2/resources/config.yaml | 4 +- cmd/v2/service/sshService.go | 112 ++++++++++- cmd/v2/service/ssh_test.go | 20 +- cmd/v2/ui/tool_gen.go | 34 +++- cmd/v2/ui/tool_term.go | 361 ++++++++++++++++++++++++++++++----- cmd/v2/ui/toolwindow.go | 2 +- 9 files changed, 488 insertions(+), 68 deletions(-) diff --git a/cmd/v2/FyneApp.toml b/cmd/v2/FyneApp.toml index bbc3df470..4c5ddd5c0 100644 --- a/cmd/v2/FyneApp.toml +++ b/cmd/v2/FyneApp.toml @@ -4,5 +4,5 @@ Website = "http://legu.cc" Icon = "app.png" Name = "RobotGUI" ID = "cc.legu.app" - Version = "1.0.9" - Build = 10 + Version = "1.0.11" + Build = 14 diff --git a/cmd/v2/lib/common/lang.go b/cmd/v2/lib/common/lang.go index bff3697e0..d0d04273a 100644 --- a/cmd/v2/lib/common/lang.go +++ b/cmd/v2/lib/common/lang.go @@ -92,7 +92,7 @@ const ( TOOLBAR_GEN = "Luban" TOOLBAR_SEC = "密码器" TOOLBAR_WEL = "欢迎" - TOOLBAR_TERM = "终端" + TOOLBAR_TERM = "同步配置" TOOLBAR_PB = "protobuf" //monitor diff --git a/cmd/v2/model/ssh.go b/cmd/v2/model/ssh.go index 0926c8a6a..989262c9b 100644 --- a/cmd/v2/model/ssh.go +++ b/cmd/v2/model/ssh.go @@ -1,9 +1,16 @@ package model type SSHModel struct { - Ip string - Port string - UserName string - Password string - CmdLast string + Ip string + Port string + UserName string + Password string + LocalDir string + RemoteDir string + ///// + ServerIp string + WorkDir string + LubanCli string + DataDir string + JsonDir string } diff --git a/cmd/v2/resources/config.yaml b/cmd/v2/resources/config.yaml index 1e477ef6d..a1f10234a 100644 --- a/cmd/v2/resources/config.yaml +++ b/cmd/v2/resources/config.yaml @@ -1,9 +1,9 @@ upgradeUrl: http://10.0.0.9:8080/ services: - service: - sid: 1 + sid: "df01" name: 外网 - url: ws://119.3.89.14:7891/gateway + url: ws://119.3.89.14:9891/gateway - service: sid: "dfz" name: 赵长远 diff --git a/cmd/v2/service/sshService.go b/cmd/v2/service/sshService.go index 35870c95f..532d3ab42 100644 --- a/cmd/v2/service/sshService.go +++ b/cmd/v2/service/sshService.go @@ -7,16 +7,28 @@ import ( "net" "os" "path" + "path/filepath" + "runtime" + "sync" "time" + "github.com/pkg/errors" "github.com/pkg/sftp" "github.com/sirupsen/logrus" "golang.org/x/crypto/ssh" ) +var sftpCli *sftp.Client +var sftpOne sync.Once + type SSHService struct { 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 { @@ -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 { return err } + + sftpCli, err = sftp.NewClient(ss.Client) 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) { var ( session *ssh.Session @@ -109,7 +148,6 @@ func (ss *SSHService) RunShell(shell string) { } else { ss.LastResult = string(output) } - } //单个copy @@ -117,11 +155,21 @@ func (ss *SSHService) ScpCopy(localFilePath, remoteDir string) error { var ( 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 { return fmt.Errorf("new sftp client error: %w", err) } - defer sftpClient.Close() + + // defer sftpCli.Close() srcFile, err := os.Open(localFilePath) if err != nil { @@ -130,8 +178,15 @@ func (ss *SSHService) ScpCopy(localFilePath, remoteDir string) error { } defer srcFile.Close() - var remoteFileName = path.Base(localFilePath) - dstFile, err := sftpClient.Create(path.Join(remoteDir, remoteFileName)) + var remoteFileName string + 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 { log.Println("scpCopy:", err) return err @@ -143,10 +198,48 @@ func (ss *SSHService) ScpCopy(localFilePath, remoteDir string) error { return fmt.Errorf("read local file failed: %w", err) } - dstFile.Write(fileByte) + if _, err := dstFile.Write(fileByte); err != nil { + return err + } 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) { sftpClient, err := sftp.NewClient(ss.Client) if err != nil { @@ -187,3 +280,8 @@ func (ss *SSHService) Scp(targetDir, srcFileName string) (int, error) { } return n, nil } + +type CopyFiles struct { + Dir string + FileName string +} diff --git a/cmd/v2/service/ssh_test.go b/cmd/v2/service/ssh_test.go index bfbab6e97..86a1b264a 100644 --- a/cmd/v2/service/ssh_test.go +++ b/cmd/v2/service/ssh_test.go @@ -2,6 +2,8 @@ package service import ( "fmt" + "path" + "path/filepath" "testing" ) @@ -36,9 +38,21 @@ func TestScp(t *testing.T) { if err != nil { t.Fatal(err) } - - if err := ssh.ScpCopy(`E:/svn/dreamworks/client/dreamworks/ExcelFile/testscp.txt`, "/opt"); err != nil { + path := filepath.Join(`E:/svn/dreamworks/client/dreamworks/ExcelFile/JSON/`, "game_vikingchallenge.json") + fmt.Println(path) + if err := ssh.ScpCopy(path, "/opt/json/"); err != nil { 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) } diff --git a/cmd/v2/ui/tool_gen.go b/cmd/v2/ui/tool_gen.go index 28f3e7adc..fd007ceaa 100644 --- a/cmd/v2/ui/tool_gen.go +++ b/cmd/v2/ui/tool_gen.go @@ -193,7 +193,6 @@ func (this *appGen) LazyInit(obs observer.Observer) error { this.goList.itemList.UpdateItem(i, widget.NewCheck(v.Text, nil)) } this.goList.changeFileCount() - // this.goList.titleLabel.SetText(fmt.Sprintf("(%d/%d)", len(this.goList.selItemIds), this.goList.fileTotal)) 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.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() } @@ -257,7 +257,6 @@ func (this *appGen) LazyInit(obs observer.Observer) error { list.itemList.UpdateItem(i, widget.NewCheck(v.Text, nil)) } this.jsonList.changeFileCount() - // list.titleLabel.SetText(fmt.Sprintf("(%d/%d)", len(list.selItemIds), list.fileTotal)) 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 { f.itemList = widget.NewList( 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) { f.fileTotal = 0 @@ -514,6 +537,11 @@ func (f *fileList) changeFileCount() { f.titleLabel.SetText(fmt.Sprintf("(%d/%d)", len(f.selItemIds), f.fileTotal)) } +type CopyFiles struct { + Dir string + FileName string +} + func (a *appGen) GetAppName() string { return common.TOOLBAR_GEN } diff --git a/cmd/v2/ui/tool_term.go b/cmd/v2/ui/tool_term.go index 39b28c4d7..548520062 100644 --- a/cmd/v2/ui/tool_term.go +++ b/cmd/v2/ui/tool_term.go @@ -2,12 +2,21 @@ package ui import ( "errors" + "fmt" "go_dreamfactory/cmd/v2/lib/common" "go_dreamfactory/cmd/v2/model" "go_dreamfactory/cmd/v2/service" "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/canvas" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/layout" @@ -22,13 +31,26 @@ type appTerm struct { obs observer.Observer sshService *service.SSHService + + jsonList *fileList //json列表 + cProgress *widget.ProgressBarInfinite //连接进度条进度条 + upProgress *widget.ProgressBar //上传进度条 + endProgress sync.WaitGroup } func (this *appTerm) LazyInit(obs observer.Observer) error { this.obs = obs 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.Objects = []fyne.CanvasObject{} @@ -38,26 +60,15 @@ func (this *appTerm) LazyInit(obs observer.Observer) error { //left-top localDir := widget.NewEntry() - localDir.PlaceHolder = `本地目录` + localDir.PlaceHolder = `本地Json目录` remoteDir := widget.NewEntry() remoteDir.PlaceHolder = `远程目录` - - 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) + remoteDir.Text = "/home/liwei/go_dreamfactory/bin/json" //config ip := widget.NewEntry() + ip.PlaceHolder = "10.0.0.9" port := widget.NewEntry() port.Text = "22" //default port port.PlaceHolder = "端口" @@ -67,40 +78,115 @@ func (this *appTerm) LazyInit(obs observer.Observer) error { password.PlaceHolder = "密码" 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 if sshConf != nil { ip.Text = sshConf.Ip port.Text = sshConf.Port userName.Text = sshConf.UserName 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( - &widget.FormItem{Text: "IP:", Widget: container.NewBorder(nil, nil, nil, port, ip)}, - &widget.FormItem{Text: "用户名:", Widget: userName}, - passwordItem, + svnForm := widget.NewForm( + &widget.FormItem{Text: "服务地址", Widget: lubanAddr}, + &widget.FormItem{Text: "工作目录", Widget: container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() { + openFolder(workDir) + }), workDir)}, + &widget.FormItem{Text: "LubanCli", Widget: lubanCli}, + &widget.FormItem{Text: "Data目录", Widget: dataDir}, + &widget.FormItem{Text: "JSON目录", Widget: jsonDir}, ) + // 非明文显示 passwordItem.Widget.Refresh() // save func - saveBtn := widget.NewButtonWithIcon("保存配置", theme.DocumentSaveIcon(), func() { + saveFunc := func() { if err := service.GetDbService().SaveSSHConf(&model.SSHModel{ - Ip: ip.Text, - UserName: userName.Text, - Password: password.Text, - Port: port.Text, + Ip: ip.Text, + UserName: userName.Text, + Password: password.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 { logrus.WithField("err", err).Debug("保存配置") } - logrus.Debug("save term conf") - }) + } + saveBtn1 := widget.NewButtonWithIcon("保存配置", theme.DocumentSaveIcon(), saveFunc) + + saveBtn2 := widget.NewButtonWithIcon("保存配置", theme.DocumentSaveIcon(), saveFunc) // 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() { + this.cProgress.Show() + this.cProgress.Start() ciphers := []string{} + + if ip.Text == "" { + dialog.ShowError(errors.New("IP未填写"), toolWin.w) + return + } if userName.Text == "" { dialog.ShowError(errors.New("账号未填写"), toolWin.w) return @@ -113,42 +199,230 @@ func (this *appTerm) LazyInit(obs observer.Observer) error { dialog.ShowError(errors.New("端口未填写"), toolWin.w) return } + + if localDir.Text == "" { + dialog.ShowError(errors.New("JSON目录未填写"), toolWin.w) + return + } + + if remoteDir.Text == "" { + dialog.ShowError(errors.New("远程目录未填写"), toolWin.w) + return + } connBtn.Disable() err := this.sshService.Connect(userName.Text, password.Text, ip.Text, "", cast.ToInt(port.Text), ciphers) if err != nil { dialog.ShowError(err, toolWin.w) + this.cProgress.Stop() + this.cProgress.Hide() connBtn.Enable() 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() } } - //excute - excuteBtn := &widget.Button{Text: "执行", Icon: theme.ConfirmIcon()} - excuteBtn.TypedKey(&fyne.KeyEvent{Name: fyne.KeyEnter}) - excuteBtn.OnTapped = func() { - output.Text = "" - excuteBtn.Disable() + // 刷新JSON列表 + refreshBtn.Disable() + refreshBtn.OnTapped = func() { defer func() { - excuteBtn.Enable() + 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 + } + } + + } + + //使用说明 + helpBtn1 := widget.NewButtonWithIcon("", theme.QuestionIcon(), func() { + quesWin := fyne.CurrentApp().NewWindow("同步JSON使用说明") + 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() { + syncBtn.Enable() + this.upProgress.Hide() }() if this.sshService.Client == nil { dialog.ShowError(errors.New("请先连接终端"), toolWin.w) 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() + } + + 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) } - btns := container.NewHBox(excuteBtn, &layout.Spacer{}, saveBtn, connBtn) + // SVN更新 + svnBtn.OnTapped = func() { + this.cProgress.Show() + this.cProgress.Start() + svnBtn.Disable() + 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), + ) - // layout - split := container.NewVSplit(container.NewGridWithColumns(2, - dirForm, - container.NewBorder(configForm, btns, widget.NewSeparator(), nil)), output) - split.Offset = 0.25 - content.Objects = append(content.Objects, split) + 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 @@ -167,7 +441,6 @@ func (a *appTerm) OnClose() bool { if a.sshService.Client != nil { a.sshService.Client.Close() } - }, toolWin.w) return true } diff --git a/cmd/v2/ui/toolwindow.go b/cmd/v2/ui/toolwindow.go index 04fc85cdd..08b9e9c6e 100644 --- a/cmd/v2/ui/toolwindow.go +++ b/cmd/v2/ui/toolwindow.go @@ -46,7 +46,7 @@ func NewToolWindow(ui *UIImpl, parent fyne.Window) ToolWindow { openApp1(common.TOOLBAR_SEC) }), - widget.NewToolbarAction(theme.ContentUndoIcon(), func() { + widget.NewToolbarAction(theme.MailSendIcon(), func() { openApp1(common.TOOLBAR_TERM) }),