789 lines
21 KiB
Go
789 lines
21 KiB
Go
package ui
|
||
|
||
import (
|
||
"fmt"
|
||
"go_dreamfactory/cmd/v2/lib/common"
|
||
os_storage "go_dreamfactory/cmd/v2/lib/storage"
|
||
"go_dreamfactory/cmd/v2/service"
|
||
"go_dreamfactory/cmd/v2/service/observer"
|
||
"image/color"
|
||
"os/exec"
|
||
"path/filepath"
|
||
"runtime"
|
||
"strings"
|
||
"sync"
|
||
|
||
"github.com/pkg/errors"
|
||
|
||
"fyne.io/fyne/v2"
|
||
"fyne.io/fyne/v2/canvas"
|
||
"fyne.io/fyne/v2/container"
|
||
"fyne.io/fyne/v2/dialog"
|
||
"fyne.io/fyne/v2/layout"
|
||
"fyne.io/fyne/v2/theme"
|
||
"fyne.io/fyne/v2/widget"
|
||
"github.com/sirupsen/logrus"
|
||
"github.com/spf13/cast"
|
||
)
|
||
|
||
type appTerm struct {
|
||
appAdapter
|
||
|
||
obs observer.Observer
|
||
sshService *service.SSHService
|
||
|
||
jsonList *common.ItemList //json列表
|
||
cProgress *widget.ProgressBarInfinite //连接进度条进度条
|
||
upProgress *widget.ProgressBar //上传进度条
|
||
endProgress sync.WaitGroup
|
||
|
||
downloadList *common.ItemList //download列表
|
||
}
|
||
|
||
func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer) error {
|
||
app.obs = obs
|
||
app.sshService = &service.SSHService{}
|
||
app.jsonList = common.NewItemList()
|
||
|
||
//progress
|
||
app.cProgress = widget.NewProgressBarInfinite()
|
||
app.cProgress.Hide()
|
||
|
||
app.upProgress = widget.NewProgressBar()
|
||
app.upProgress.Hide()
|
||
|
||
app.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_TERM, theme.MailSendIcon(), nil)
|
||
content := container.NewMax()
|
||
content.Objects = []fyne.CanvasObject{}
|
||
|
||
//load term conf
|
||
storage, _ := os_storage.NewOSStorage()
|
||
conf, err := storage.LoadConfig()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
//left-top
|
||
localDir := widget.NewEntry()
|
||
localDir.PlaceHolder = `本地Json目录`
|
||
|
||
remoteDir := widget.NewEntry()
|
||
remoteDir.PlaceHolder = `远程目录`
|
||
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 = "端口"
|
||
userName := widget.NewEntry()
|
||
userName.PlaceHolder = "账号"
|
||
password := widget.NewPasswordEntry()
|
||
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, toolWin.w)
|
||
}), 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目录"
|
||
|
||
svnForm := widget.NewForm(
|
||
&widget.FormItem{Text: "服务地址", Widget: lubanAddr},
|
||
&widget.FormItem{Text: "工作目录", Widget: container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
|
||
openFolder(workDir, toolWin.w)
|
||
}), workDir)},
|
||
&widget.FormItem{Text: "LubanCli", Widget: lubanCli},
|
||
&widget.FormItem{Text: "Data目录", Widget: dataDir},
|
||
&widget.FormItem{Text: "JSON目录", Widget: jsonDir},
|
||
)
|
||
|
||
//set input entry
|
||
if conf.SyncConf != nil {
|
||
ip.Text = conf.SyncConf.Ip
|
||
port.Text = conf.SyncConf.Port
|
||
userName.Text = conf.SyncConf.UserName
|
||
password.Text = conf.SyncConf.Password
|
||
localDir.Text = conf.SyncConf.LocalDir
|
||
remoteDir.Text = conf.SyncConf.RemoteDir
|
||
// //
|
||
lubanAddr.Text = conf.SyncConf.ServerIp
|
||
workDir.Text = conf.SyncConf.WorkDir
|
||
lubanCli.Text = conf.SyncConf.LubanCli
|
||
dataDir.Text = conf.SyncConf.DataDir
|
||
jsonDir.Text = conf.SyncConf.JsonDir
|
||
} else {
|
||
conf.SyncConf = &os_storage.SyncConfig{
|
||
Ip: "10.0.0.9",
|
||
UserName: "root",
|
||
Password: "Legu.cc()123",
|
||
RemoteDir: "/home/liwei/go_dreamfactory/bin/json/",
|
||
|
||
ServerIp: "10.0.1.11",
|
||
LubanCli: `Luban.Client\Luban.Client.exe`,
|
||
DataDir: "Datas",
|
||
JsonDir: `output\json`,
|
||
}
|
||
}
|
||
|
||
// 解决文本没显示的问题
|
||
passwordItem.Widget.Refresh()
|
||
ip.Refresh()
|
||
localDir.Refresh()
|
||
workDir.Refresh()
|
||
|
||
// save func
|
||
saveFunc := func() {
|
||
syncConf := &os_storage.SyncConfig{
|
||
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,
|
||
}
|
||
conf.SyncConf = syncConf
|
||
if err := storage.StoreConfig(conf); err != nil {
|
||
logrus.Error(err)
|
||
}
|
||
}
|
||
saveBtn1 := widget.NewButtonWithIcon("保存配置", theme.DocumentSaveIcon(), saveFunc)
|
||
|
||
saveBtn2 := widget.NewButtonWithIcon("保存配置", theme.DocumentSaveIcon(), saveFunc)
|
||
|
||
// conn func
|
||
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()}
|
||
excelBtn := &widget.Button{Text: "更新Excel", Icon: theme.FolderIcon()}
|
||
explorBtn := &widget.Button{Text: "资源管理器", Icon: theme.FolderIcon()}
|
||
dlBtn := widget.NewButtonWithIcon("", theme.DownloadIcon(), nil)
|
||
|
||
searchEntry := widget.NewEntry()
|
||
|
||
// 全选/全取消
|
||
allSelBtn := &widget.Button{Icon: theme.CheckButtonCheckedIcon()}
|
||
allCancelBtn := &widget.Button{Icon: theme.CheckButtonIcon()}
|
||
allSelBtn.Hide()
|
||
|
||
// 连接
|
||
connBtn.OnTapped = func() {
|
||
app.cProgress.Show()
|
||
app.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
|
||
}
|
||
if password.Text == "" {
|
||
dialog.ShowError(errors.New("密码未填写"), toolWin.w)
|
||
return
|
||
}
|
||
if port.Text == "" {
|
||
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 := app.sshService.Connect(userName.Text, password.Text, ip.Text, "", cast.ToInt(port.Text), ciphers)
|
||
if err != nil {
|
||
dialog.ShowError(err, toolWin.w)
|
||
app.cProgress.Stop()
|
||
app.cProgress.Hide()
|
||
connBtn.Enable()
|
||
return
|
||
} else {
|
||
app.jsonList.LoadItem(localDir.Text)
|
||
|
||
app.cProgress.Stop()
|
||
app.cProgress.Hide()
|
||
disConnBtn.Enable()
|
||
syncBtn.Enable()
|
||
app.upProgress.Hide()
|
||
allCancelBtn.Show()
|
||
allSelBtn.Hide()
|
||
refreshBtn.Enable()
|
||
dlBtn.Enable()
|
||
}
|
||
}
|
||
|
||
// 刷新JSON列表
|
||
refreshBtn.Disable()
|
||
reloadItem := func() {
|
||
defer func() {
|
||
syncBtn.Enable()
|
||
allSelBtn.Hide()
|
||
allCancelBtn.Show()
|
||
}()
|
||
app.jsonList.LoadItem(localDir.Text)
|
||
}
|
||
refreshBtn.OnTapped = reloadItem
|
||
|
||
// 断开
|
||
disConnBtn.Disable()
|
||
disConnBtn.OnTapped = func() {
|
||
defer func() {
|
||
app.jsonList.Reset()
|
||
connBtn.Enable()
|
||
disConnBtn.Disable()
|
||
syncBtn.Disable()
|
||
allSelBtn.Hide()
|
||
allCancelBtn.Show()
|
||
refreshBtn.Disable()
|
||
dlBtn.Disable()
|
||
}()
|
||
app.sshService.Close()
|
||
}
|
||
|
||
//资源管理器
|
||
openExplor := func(dir string) {
|
||
if runtime.GOOS == "windows" {
|
||
if err := exec.Command("explorer", filepath.Join(dir)).Start(); err != nil {
|
||
dialog.ShowError(errors.WithMessage(err, "请确认Json目录是否填写正确"), toolWin.w)
|
||
return
|
||
}
|
||
}
|
||
}
|
||
explorBtn.OnTapped = func() {
|
||
// logrus.Debug(localDir.Text)
|
||
if localDir.Text == "" {
|
||
common.ShowTip("Json目录必须填写")
|
||
} else {
|
||
openExplor(localDir.Text)
|
||
}
|
||
}
|
||
|
||
//使用说明
|
||
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 (保持一致)
|
||
* Data目录: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()
|
||
syncNext := func() {
|
||
defer func() {
|
||
syncBtn.Enable()
|
||
app.upProgress.Hide()
|
||
reloadItem()
|
||
dialog.ShowInformation("提示", "所有文件均上传完毕,需等1-2分钟待文件热更", toolWin.w)
|
||
}()
|
||
syncBtn.Disable()
|
||
app.upProgress.Show()
|
||
app.upProgress.SetValue(0)
|
||
|
||
len := len(app.jsonList.SelItemIds)
|
||
num := 0.0
|
||
|
||
increment := func(wg *sync.WaitGroup) {
|
||
num += float64(1) / float64(len)
|
||
app.upProgress.SetValue(num)
|
||
wg.Done()
|
||
}
|
||
|
||
for _, fileName := range app.jsonList.SelItemIds {
|
||
app.endProgress.Add(1)
|
||
go func(fn string) {
|
||
// time.Sleep(time.Second * time.Duration(rand.Intn(3)))
|
||
if err := app.sshService.ScpCopy(filepath.Join(localDir.Text, fn), remoteDir.Text); err != nil {
|
||
logrus.WithField("err", err).Error("同步json")
|
||
common.ShowTip(err.Error())
|
||
}
|
||
increment(&app.endProgress)
|
||
// 移除已上传的
|
||
app.jsonList.DeleteItem(fn)
|
||
common.ShowTip(fmt.Sprintf("%s 成功上传", fn))
|
||
}(fileName)
|
||
}
|
||
app.endProgress.Wait()
|
||
app.upProgress.SetValue(1)
|
||
}
|
||
syncBtn.OnTapped = func() {
|
||
if app.sshService.Client == nil {
|
||
dialog.ShowError(errors.New("请先连接终端"), toolWin.w)
|
||
return
|
||
}
|
||
|
||
//SVN更新提示
|
||
dc := dialog.NewConfirm("提示", "是否要进行SVN更新?", func(b bool) {
|
||
if b {
|
||
common.ShowTip("单击【SVN更新】按钮进行更新")
|
||
svnBtn.FocusGained()
|
||
return
|
||
} else {
|
||
if len(app.jsonList.SelItemIds) == 0 {
|
||
common.ShowTip("没有选择任何文件,或尝试点击【刷新】")
|
||
return
|
||
}
|
||
syncNext()
|
||
}
|
||
}, toolWin.w)
|
||
dc.SetConfirmText("必须的")
|
||
dc.SetDismissText("我拿生命担保无需更新")
|
||
dc.Show()
|
||
}
|
||
|
||
// excel更新
|
||
excelBtn.OnTapped = func() {
|
||
if workDir.Text == "" {
|
||
common.ShowTip("工作目录必须填写")
|
||
} else {
|
||
openExplor(workDir.Text)
|
||
}
|
||
}
|
||
|
||
// SVN更新
|
||
svnNext := func() {
|
||
defer func() {
|
||
app.cProgress.Hide()
|
||
app.cProgress.Stop()
|
||
svnBtn.Enable()
|
||
}()
|
||
svnBtn.Disable()
|
||
app.cProgress.Show()
|
||
app.cProgress.Start()
|
||
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
|
||
}
|
||
}
|
||
svnBtn.OnTapped = func() {
|
||
|
||
//提示更新excel
|
||
dc := dialog.NewConfirm("提示", "是否要更新excel?", func(b bool) {
|
||
if b {
|
||
//打开资源管理器
|
||
openExplor(workDir.Text)
|
||
return
|
||
} else {
|
||
svnNext()
|
||
}
|
||
}, toolWin.w)
|
||
dc.SetConfirmText("必须的")
|
||
dc.SetDismissText("我拿生命担保无需更新")
|
||
dc.Show()
|
||
}
|
||
|
||
// 全部取消
|
||
allCancelBtn.OnTapped = func() {
|
||
defer func() {
|
||
allCancelBtn.Hide()
|
||
allSelBtn.Show()
|
||
}()
|
||
for i, v := range app.jsonList.CachedList.Items {
|
||
app.jsonList.CachedList.Items[i].Checked = true
|
||
app.jsonList.SelItemIds = append(app.jsonList.SelItemIds, v.Text)
|
||
app.jsonList.ItemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
|
||
}
|
||
app.jsonList.ItemList.Refresh()
|
||
}
|
||
|
||
// 全选
|
||
allSelBtn.OnTapped = func() {
|
||
defer func() {
|
||
allCancelBtn.Show()
|
||
allSelBtn.Hide()
|
||
}()
|
||
app.jsonList.SelItemIds = []string{}
|
||
for i, v := range app.jsonList.CachedList.Items {
|
||
app.jsonList.CachedList.Items[i].Checked = false
|
||
app.jsonList.ItemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
|
||
}
|
||
app.jsonList.ItemList.Refresh()
|
||
}
|
||
|
||
// 搜索
|
||
searchEntry.PlaceHolder = "搜索"
|
||
searchEntry.OnChanged = func(s string) {
|
||
if app.sshService.Client == nil {
|
||
dialog.ShowError(errors.New("请先连接终端"), toolWin.w)
|
||
return
|
||
}
|
||
if s == "" {
|
||
reloadItem()
|
||
} else {
|
||
// go func() {
|
||
newList := []common.Item{}
|
||
for _, v := range app.jsonList.SearchItem {
|
||
if strings.Contains(v.Text, s) {
|
||
newList = append(newList, v)
|
||
}
|
||
}
|
||
app.jsonList.CachedList.Items = newList
|
||
app.jsonList.ItemList.Refresh()
|
||
// }()
|
||
}
|
||
}
|
||
|
||
// 下载日志
|
||
dlBtn.Disable()
|
||
dlBtn.OnTapped = func() {
|
||
w := app.createDownloadWindow()
|
||
w.Show()
|
||
w.SetCloseIntercept(func() {
|
||
dlBtn.Enable()
|
||
w.Close()
|
||
})
|
||
dlBtn.Disable()
|
||
}
|
||
|
||
// 创建json列表
|
||
app.jsonList.ItemList = app.jsonList.CreateDefaultCheckList()
|
||
|
||
btns1 := container.NewHBox(helpBtn1, dlBtn, &layout.Spacer{}, saveBtn1, connBtn, disConnBtn)
|
||
btns2 := container.NewHBox(helpBtn2, &layout.Spacer{}, saveBtn2, excelBtn, svnBtn)
|
||
|
||
split := container.NewHSplit(container.NewVBox(canvas.NewText("---只能在非上产环境!!!同步Json的操作仅限于数值热更,非结构热更---", color.RGBA{255, 0, 0, 255}), configForm,
|
||
btns1, svnForm, btns2, app.cProgress), container.NewBorder(
|
||
container.NewBorder(nil, nil, container.NewHBox(allCancelBtn, allSelBtn, syncBtn, refreshBtn), container.NewHBox(explorBtn), searchEntry),
|
||
nil, nil, nil, app.jsonList.ItemList))
|
||
split.Offset = 0.45
|
||
content.Objects = append(content.Objects, container.NewBorder(nil, app.upProgress, nil, nil, split))
|
||
|
||
app.tabItem.Content = content
|
||
|
||
return nil
|
||
}
|
||
|
||
func (a *appTerm) GetAppName() string {
|
||
return common.TOOLBAR_TERM
|
||
}
|
||
func (a *appTerm) Icon() fyne.Resource {
|
||
return theme.MailSendIcon()
|
||
}
|
||
|
||
func OpenExplor(dir string) {
|
||
if dir == "" {
|
||
common.ShowTip("资源管理器路径错误")
|
||
return
|
||
}
|
||
if runtime.GOOS == "windows" {
|
||
if err := exec.Command("explorer", filepath.Join(dir)).Start(); err != nil {
|
||
dialog.ShowError(errors.WithMessage(err, "请确认Json目录是否填写正确"), toolWin.w)
|
||
return
|
||
}
|
||
}
|
||
}
|
||
|
||
func (a *appTerm) OnClose() bool {
|
||
dialog.ShowConfirm("关闭终端", "你希望断开连接吗?", func(b bool) {
|
||
if !b {
|
||
return
|
||
}
|
||
if a.sshService.Client != nil {
|
||
a.sshService.Client.Close()
|
||
}
|
||
}, toolWin.w)
|
||
return true
|
||
}
|
||
|
||
func (a *appTerm) createDownloadWindow() fyne.Window {
|
||
w := toolWin.app.NewWindow("日志")
|
||
|
||
a.downloadList = common.NewItemList()
|
||
|
||
a.downloadList.ItemList = a.downloadList.CreateDownloadList()
|
||
|
||
remoteLogDirEntry := widget.NewEntry()
|
||
remoteLogDirEntry.PlaceHolder = "下载到"
|
||
remoteLogDirEntry.Text = "/home/liwei/go_dreamfactory/bin/log/"
|
||
|
||
saveDirEntry := widget.NewEntry()
|
||
saveDirEntry.PlaceHolder = "保存目录"
|
||
|
||
editorEntry := widget.NewEntry()
|
||
editorEntry.PlaceHolder = "编辑器可执行文件路径"
|
||
|
||
// config
|
||
confForm := widget.NewForm(
|
||
widget.NewFormItem("远程目录", remoteLogDirEntry),
|
||
widget.NewFormItem("下载目录", saveDirEntry),
|
||
widget.NewFormItem("编辑器", container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
|
||
openFile(editorEntry, w)
|
||
}), editorEntry)),
|
||
)
|
||
|
||
// 进度条
|
||
downloadProgress := widget.NewProgressBarInfinite()
|
||
|
||
var (
|
||
storage os_storage.Storage
|
||
conf *os_storage.Config
|
||
err error
|
||
)
|
||
defer func() {
|
||
downloadProgress.Hide()
|
||
//加载配置
|
||
storage, _ = os_storage.NewOSStorage()
|
||
conf, err = storage.LoadConfig()
|
||
if err != nil {
|
||
return
|
||
}
|
||
|
||
// sshConf = service.GetDbService().GetSSHConf(common.BUCKET_SSHCONF)
|
||
if conf.SyncConf != nil {
|
||
if conf.SyncConf.LogDir == "" {
|
||
remoteLogDirEntry.Text = "/home/liwei/go_dreamfactory/bin/log/"
|
||
} else {
|
||
remoteLogDirEntry.Text = conf.SyncConf.LogDir
|
||
}
|
||
|
||
saveDirEntry.Text = conf.SyncConf.SaveDir
|
||
editorEntry.Text = conf.SyncConf.Editor
|
||
} else {
|
||
conf.SyncConf = &os_storage.SyncConfig{}
|
||
}
|
||
|
||
remoteLogDirEntry.Refresh()
|
||
saveDirEntry.Refresh()
|
||
editorEntry.Refresh()
|
||
|
||
//load list
|
||
if remoteLogDirEntry.Text == "" {
|
||
return
|
||
}
|
||
files, err := a.sshService.GetRemoteDir(remoteLogDirEntry.Text)
|
||
if err != nil {
|
||
dialog.ShowError(err, toolWin.w)
|
||
return
|
||
}
|
||
|
||
for _, f := range files {
|
||
a.downloadList.AddItem(common.Item{Id: f.FileName, Text: f.FileName, Size: f.Size})
|
||
}
|
||
}()
|
||
|
||
//下载
|
||
allDownloadBtn := widget.NewButtonWithIcon("下载", theme.DownloadIcon(), nil)
|
||
DownloadDirBtn := widget.NewButtonWithIcon("打开下载目录", theme.FolderIcon(), nil)
|
||
EditorBtn := widget.NewButtonWithIcon("打开编辑器", theme.FolderIcon(), nil)
|
||
saveConfBtn := widget.NewButtonWithIcon("保存配置", theme.DocumentSaveIcon(), func() {
|
||
// 保存配置
|
||
conf.SyncConf.LogDir = remoteLogDirEntry.Text
|
||
conf.SyncConf.SaveDir = saveDirEntry.Text
|
||
conf.SyncConf.Editor = editorEntry.Text
|
||
if err := storage.StoreConfig(conf); err != nil {
|
||
logrus.Error(err)
|
||
}
|
||
})
|
||
|
||
allSelBtn := &widget.Button{Icon: theme.CheckButtonCheckedIcon()}
|
||
allCancelBtn := &widget.Button{Icon: theme.CheckButtonIcon()}
|
||
allSelBtn.Hide()
|
||
|
||
// 全部取消
|
||
allCancelBtn.OnTapped = func() {
|
||
defer func() {
|
||
allCancelBtn.Hide()
|
||
allSelBtn.Show()
|
||
}()
|
||
dlist := a.downloadList
|
||
for i, v := range dlist.CachedList.Items {
|
||
dlist.CachedList.Items[i].Checked = true
|
||
dlist.SelItemIds = append(dlist.SelItemIds, v.Text)
|
||
dlist.ItemList.UpdateItem(i, container.NewHBox(
|
||
widget.NewCheck(v.Text, nil),
|
||
&layout.Spacer{},
|
||
widget.NewLabel(common.ConvertFileSize(v.Size))))
|
||
}
|
||
dlist.ItemList.Refresh()
|
||
}
|
||
|
||
// 全选
|
||
allSelBtn.OnTapped = func() {
|
||
defer func() {
|
||
allCancelBtn.Show()
|
||
allSelBtn.Hide()
|
||
}()
|
||
dlist := a.downloadList
|
||
dlist.SelItemIds = []string{}
|
||
for i, v := range dlist.CachedList.Items {
|
||
dlist.CachedList.Items[i].Checked = false
|
||
dlist.ItemList.UpdateItem(i, container.NewHBox(
|
||
widget.NewCheck(v.Text, nil),
|
||
&layout.Spacer{},
|
||
widget.NewLabel(common.ConvertFileSize(v.Size))))
|
||
}
|
||
dlist.ItemList.Refresh()
|
||
}
|
||
|
||
// 打开下载目录
|
||
DownloadDirBtn.OnTapped = func() {
|
||
OpenExplor(saveDirEntry.Text)
|
||
}
|
||
|
||
EditorBtn.OnTapped = func() {
|
||
if editorEntry.Text == "" {
|
||
common.ShowTip("请配置编辑器")
|
||
return
|
||
}
|
||
if runtime.GOOS == "windows" {
|
||
for _, v := range a.downloadList.SelItemIds {
|
||
if err := exec.Command(editorEntry.Text, filepath.Join(saveDirEntry.Text, v)).Start(); err != nil {
|
||
dialog.ShowError(errors.WithMessage(err, "请确认编辑器目录是否填写正确"), toolWin.w)
|
||
return
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
//使用说明
|
||
helpBtn := widget.NewButtonWithIcon("", theme.QuestionIcon(), func() {
|
||
quesWin := fyne.CurrentApp().NewWindow("日志使用说明")
|
||
quesWin.SetContent(widget.NewRichTextFromMarkdown(
|
||
`
|
||
* 下载远程服务日志到本地分析
|
||
* 提示:
|
||
* 远程目录 (保持一致)
|
||
* 下载目录:填写本地任意目录
|
||
* 编辑器:选择已安装的编辑器(例如:notepad++、Sublime)
|
||
* 操作:
|
||
* 选择文件,点击【打开编辑器】
|
||
`))
|
||
quesWin.Resize(fyne.NewSize(350, 200))
|
||
quesWin.SetFixedSize(true)
|
||
quesWin.CenterOnScreen()
|
||
quesWin.Show()
|
||
})
|
||
|
||
var wg sync.WaitGroup
|
||
//download
|
||
allDownloadBtn.OnTapped = func() {
|
||
downloadProgress.Show()
|
||
downloadProgress.Start()
|
||
selItems := a.downloadList.SelItemIds
|
||
if len(selItems) == 0 {
|
||
common.ShowTip("请选择下载的文件")
|
||
return
|
||
} else {
|
||
for _, item := range selItems {
|
||
wg.Add(1)
|
||
go func(name string) {
|
||
defer func() {
|
||
downloadProgress.Hide()
|
||
wg.Done()
|
||
}()
|
||
logrus.WithField("filepath", saveDirEntry.Text+name).Debug("下载")
|
||
if err := a.sshService.ScpDownload(saveDirEntry.Text, remoteLogDirEntry.Text+name); err != nil {
|
||
common.ShowTip(name + " 下载失败")
|
||
}
|
||
}(item)
|
||
}
|
||
wg.Wait()
|
||
}
|
||
}
|
||
|
||
btns := container.NewHBox(allSelBtn, allCancelBtn, allDownloadBtn, DownloadDirBtn, EditorBtn, helpBtn)
|
||
//toolbar
|
||
toolbar := container.NewBorder(nil, btns, nil, saveConfBtn, confForm)
|
||
|
||
//layout
|
||
w.SetContent(container.NewBorder(toolbar, downloadProgress, nil, nil, a.downloadList.ItemList))
|
||
|
||
w.Resize(fyne.NewSize(800, 450))
|
||
w.CenterOnScreen()
|
||
return w
|
||
}
|