520 lines
14 KiB
Go
520 lines
14 KiB
Go
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"
|
|
"go_dreamfactory/utils"
|
|
"io/ioutil"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"runtime"
|
|
"sort"
|
|
"strings"
|
|
|
|
"fyne.io/fyne/v2"
|
|
"fyne.io/fyne/v2/container"
|
|
"fyne.io/fyne/v2/dialog"
|
|
"fyne.io/fyne/v2/layout"
|
|
"fyne.io/fyne/v2/storage"
|
|
"fyne.io/fyne/v2/theme"
|
|
"fyne.io/fyne/v2/widget"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type appGen struct {
|
|
appAdapter
|
|
|
|
obs observer.Observer
|
|
goList *fileList
|
|
jsonList *fileList
|
|
}
|
|
|
|
func (this *appGen) LazyInit(obs observer.Observer) error {
|
|
this.obs = obs
|
|
this.goList = NewFileList()
|
|
this.jsonList = NewFileList()
|
|
|
|
this.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_GEN, theme.ContentCopyIcon(), nil)
|
|
|
|
// load
|
|
gt := service.GetDbService().GetLubanConf(common.BUCKET_LUBANCONF)
|
|
logrus.Debugf("%v", gt)
|
|
|
|
content := container.NewMax()
|
|
content.Objects = []fyne.CanvasObject{}
|
|
|
|
serverAddr := widget.NewEntry()
|
|
serverAddr.PlaceHolder = "服务器地址 例如: 10.0.1.11"
|
|
|
|
projectDir := widget.NewEntry()
|
|
projectDir.PlaceHolder = `项目目录 例如: E:\projects\workspace\go_dreamfactory\`
|
|
|
|
workDir := widget.NewEntry()
|
|
workDir.PlaceHolder = `LuBan目录 例如: E:\svn\dreamworks\client\dreamworks\ExcelFile\`
|
|
|
|
// client
|
|
client := widget.NewEntry()
|
|
client.Text = `Luban.Client\Luban.Client.exe`
|
|
client.PlaceHolder = `配置Luban Client.exe路径`
|
|
|
|
//define
|
|
define := widget.NewEntry()
|
|
define.PlaceHolder = "定义文件"
|
|
define.Text = `Defines\\__root__.xml`
|
|
|
|
// output
|
|
outputCodeDir := widget.NewEntry()
|
|
outputCodeDir.Text = `sys\configure\structs`
|
|
outputJsonDir := widget.NewEntry()
|
|
outputJsonDir.Text = `bin\json`
|
|
|
|
//input
|
|
inputDir := widget.NewEntry()
|
|
inputDir.Text = "Datas"
|
|
|
|
tmpDir := widget.NewEntry()
|
|
tmpDir.Text = filepath.Join(`c:\tmp\`)
|
|
tmpDir.PlaceHolder = "临时目录,不要和工作目录和项目目录重复"
|
|
|
|
//genType
|
|
var genTypeText string
|
|
genType := widget.NewSelect([]string{"go", "json", "all"}, func(s string) {
|
|
genTypeText = s
|
|
})
|
|
genType.PlaceHolder = "生成类型"
|
|
|
|
if gt != nil {
|
|
serverAddr.Text = gt.ServerAddr
|
|
projectDir.Text = gt.ProjectDir
|
|
workDir.Text = gt.WorkDir
|
|
client.Text = gt.Client
|
|
genType.Selected = gt.GenType
|
|
genTypeText = gt.GenType
|
|
tmpDir.Text = gt.TmpDir
|
|
}
|
|
|
|
// 打开目录
|
|
openFolder := func(entry *widget.Entry) {
|
|
dConf := dialog.NewFolderOpen(func(lu fyne.ListableURI, err error) {
|
|
if lu == nil {
|
|
return
|
|
}
|
|
entry.Text = lu.Path()
|
|
entry.Refresh()
|
|
}, toolWin.w)
|
|
luri, _ := storage.ListerForURI(storage.NewFileURI("."))
|
|
dConf.SetLocation(luri)
|
|
dConf.SetConfirmText("打开")
|
|
dConf.SetDismissText("取消")
|
|
dConf.Resize(fyne.NewSize(750, 500))
|
|
dConf.Show()
|
|
}
|
|
|
|
form := widget.NewForm(
|
|
widget.NewFormItem("服务地址", serverAddr),
|
|
widget.NewFormItem("项目目录", container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
|
|
openFolder(projectDir)
|
|
}), projectDir)),
|
|
widget.NewFormItem("工作目录", container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
|
|
openFolder(workDir)
|
|
}), workDir)),
|
|
widget.NewFormItem("LuBan Cli", client),
|
|
widget.NewFormItem("输入目录", inputDir),
|
|
widget.NewFormItem("输出Code目录", outputCodeDir),
|
|
widget.NewFormItem("输出JSON目录", outputJsonDir),
|
|
widget.NewFormItem("临时目录", container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
|
|
openFolder(tmpDir)
|
|
}), tmpDir)),
|
|
widget.NewFormItem("生成类型", genType),
|
|
)
|
|
|
|
getType := func() string {
|
|
if genTypeText == "" {
|
|
return ""
|
|
} else {
|
|
if genTypeText == "go" {
|
|
return "code_go_json"
|
|
} else if genTypeText == "json" {
|
|
return "data_json"
|
|
} else if genTypeText == "all" {
|
|
return "code_go_json,data_json"
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
saveBtn := widget.NewButtonWithIcon("保存配置", theme.DocumentSaveIcon(), func() {
|
|
if err := service.GetDbService().SaveLubanConf(&model.GenTool{
|
|
ServerAddr: serverAddr.Text,
|
|
ProjectDir: projectDir.Text,
|
|
Client: client.Text,
|
|
WorkDir: workDir.Text,
|
|
InputDir: inputDir.Text,
|
|
OutputCodeDir: outputCodeDir.Text,
|
|
OutputJsonDir: outputJsonDir.Text,
|
|
GenType: genTypeText,
|
|
TmpDir: tmpDir.Text,
|
|
}); err != nil {
|
|
logrus.WithField("err", err).Debug("保存配置")
|
|
}
|
|
logrus.Debug("save luban conf")
|
|
})
|
|
|
|
//go
|
|
this.goList.titleLabel = widget.NewLabel("Go文件")
|
|
this.goList.titleLabel.Hide()
|
|
// 复选列表
|
|
this.goList.itemList = this.goList.createList()
|
|
|
|
// 覆盖 -go
|
|
go_allSelBtn := &widget.Button{Icon: theme.CheckButtonIcon()}
|
|
go_allCancelBtn := &widget.Button{Icon: theme.CheckButtonCheckedIcon()}
|
|
go_overrideBtn := &widget.Button{Text: "覆盖", Icon: theme.ConfirmIcon()}
|
|
go_overrideBtn.Hide()
|
|
go_allSelBtn.Hide()
|
|
|
|
// 覆盖
|
|
go_overrideBtn.OnTapped = func() {
|
|
go_overrideBtn.Disable()
|
|
defer func() {
|
|
go_overrideBtn.Enable()
|
|
this.goList.itemList.Refresh()
|
|
}()
|
|
for _, v := range this.goList.selItemIds {
|
|
// logrus.WithField("path1", filepath.Join(tmpDir.Text, "go", v)).Debug("copy go")
|
|
// logrus.WithField("path2", filepath.Join(projectDir.Text, outputCodeDir.Text, v)).Debug("copy go")
|
|
_, err := common.Copy(filepath.Join(tmpDir.Text, "go", v),
|
|
filepath.Join(projectDir.Text, outputCodeDir.Text, v))
|
|
if err != nil {
|
|
logrus.Error(err)
|
|
return
|
|
}
|
|
this.goList.deleteItem(v)
|
|
}
|
|
this.goList.changeFileCount()
|
|
}
|
|
|
|
//取消checked
|
|
go_allCancelBtn.OnTapped = func() {
|
|
defer func() {
|
|
go_allCancelBtn.Hide()
|
|
go_allSelBtn.Show()
|
|
}()
|
|
this.goList.selItemIds = []string{}
|
|
for i, v := range this.goList.cachedList.Items {
|
|
this.goList.cachedList.Items[i].Checked = false
|
|
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()
|
|
}
|
|
|
|
//选择所有
|
|
go_allSelBtn.OnTapped = func() {
|
|
defer func() {
|
|
go_allCancelBtn.Show()
|
|
go_allSelBtn.Hide()
|
|
}()
|
|
for i, v := range this.goList.cachedList.Items {
|
|
this.goList.cachedList.Items[i].Checked = true
|
|
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.itemList.Refresh()
|
|
}
|
|
|
|
// json
|
|
this.jsonList.titleLabel = widget.NewLabel("Json文件")
|
|
this.jsonList.titleLabel.Hide()
|
|
// 复选列表
|
|
this.jsonList.itemList = this.jsonList.createList()
|
|
|
|
// 覆盖 -go
|
|
json_allSelBtn := &widget.Button{Icon: theme.CheckButtonIcon()}
|
|
json_allCancelBtn := &widget.Button{Icon: theme.CheckButtonCheckedIcon()}
|
|
json_overrideBtn := &widget.Button{Text: "覆盖", Icon: theme.ConfirmIcon()}
|
|
json_overrideBtn.Hide()
|
|
json_allSelBtn.Hide()
|
|
json_overrideBtn.OnTapped = func() {
|
|
json_overrideBtn.Disable()
|
|
defer func() {
|
|
json_overrideBtn.Enable()
|
|
this.jsonList.itemList.Refresh()
|
|
}()
|
|
for _, v := range this.jsonList.selItemIds {
|
|
// logrus.WithField("path1", filepath.Join(tmpDir.Text, "json", v)).Debug("copy json")
|
|
// logrus.WithField("path2", filepath.Join(projectDir.Text, outputJsonDir.Text, v)).Debug("copy json")
|
|
_, err := common.Copy(filepath.Join(tmpDir.Text, "json", v),
|
|
filepath.Join(projectDir.Text, outputJsonDir.Text, v))
|
|
if err != nil {
|
|
logrus.Error(err)
|
|
return
|
|
}
|
|
this.jsonList.deleteItem(v)
|
|
}
|
|
this.jsonList.changeFileCount()
|
|
}
|
|
|
|
//取消checked
|
|
json_allCancelBtn.OnTapped = func() {
|
|
defer func() {
|
|
json_allCancelBtn.Hide()
|
|
json_allSelBtn.Show()
|
|
}()
|
|
list := this.jsonList
|
|
list.selItemIds = []string{}
|
|
for i, v := range list.cachedList.Items {
|
|
list.cachedList.Items[i].Checked = false
|
|
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()
|
|
}
|
|
|
|
//选择所有
|
|
json_allSelBtn.OnTapped = func() {
|
|
defer func() {
|
|
json_allCancelBtn.Show()
|
|
json_allSelBtn.Hide()
|
|
}()
|
|
list := this.jsonList
|
|
for i, v := range list.cachedList.Items {
|
|
list.cachedList.Items[i].Checked = true
|
|
list.selItemIds = append(list.selItemIds, v.Text)
|
|
list.itemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
|
|
}
|
|
list.changeFileCount()
|
|
list.itemList.Refresh()
|
|
}
|
|
|
|
genBtn := &widget.Button{Text: "生成", Icon: theme.ConfirmIcon()}
|
|
genBtn.OnTapped = func() {
|
|
genBtn.Disable()
|
|
defer func() {
|
|
genBtn.Enable()
|
|
go_allCancelBtn.Show()
|
|
go_allSelBtn.Hide()
|
|
json_allCancelBtn.Show()
|
|
json_allSelBtn.Hide()
|
|
}()
|
|
if runtime.GOOS != "windows" {
|
|
dialog.ShowError(errors.New("no support "+runtime.GOOS), toolWin.w)
|
|
return
|
|
}
|
|
|
|
if genTypeText == "" {
|
|
dialog.ShowError(errors.New("类型未选择"), toolWin.w)
|
|
return
|
|
}
|
|
|
|
commandStr := `%s -h %s -j cfg -- -d %s --input_data_dir %s --output_code_dir %s --output_data_dir %s --gen_types %s --go:bright_module_name bright -s server`
|
|
|
|
arg := fmt.Sprintf(commandStr,
|
|
filepath.Join(workDir.Text, client.Text),
|
|
serverAddr.Text,
|
|
filepath.Join(workDir.Text, define.Text),
|
|
filepath.Join(workDir.Text, inputDir.Text),
|
|
filepath.Join(tmpDir.Text, "go"),
|
|
filepath.Join(tmpDir.Text, "json"),
|
|
getType(),
|
|
)
|
|
|
|
logrus.Debug(arg)
|
|
c := exec.Command("cmd.exe", "/c", arg)
|
|
if err := c.Run(); err != nil {
|
|
dialog.ShowError(err, toolWin.w)
|
|
return
|
|
}
|
|
|
|
changeGo := func() {
|
|
this.goList.changeItem(filepath.Join(tmpDir.Text, "go"), filepath.Join(projectDir.Text, outputCodeDir.Text))
|
|
this.goList.titleLabel.SetText(fmt.Sprintf("(%d/%d个)", len(this.goList.selItemIds), this.goList.fileTotal))
|
|
go_overrideBtn.Show()
|
|
this.goList.titleLabel.Show()
|
|
}
|
|
|
|
changeJson := func() {
|
|
this.jsonList.changeItem(filepath.Join(tmpDir.Text, "json"), filepath.Join(projectDir.Text, outputJsonDir.Text))
|
|
this.jsonList.titleLabel.SetText(fmt.Sprintf("(%d/%d)", len(this.jsonList.selItemIds), this.jsonList.fileTotal))
|
|
json_overrideBtn.Show()
|
|
this.jsonList.titleLabel.Show()
|
|
}
|
|
|
|
// 更新列表
|
|
if genTypeText == "go" {
|
|
changeGo()
|
|
} else if genTypeText == "json" {
|
|
changeJson()
|
|
} else if genTypeText == "all" {
|
|
changeGo()
|
|
changeJson()
|
|
}
|
|
}
|
|
|
|
//使用说明
|
|
desBtn := widget.NewButtonWithIcon("", theme.QuestionIcon(), func() {
|
|
quesWin := fyne.CurrentApp().NewWindow("使用说明")
|
|
quesWin.SetContent(widget.NewRichTextFromMarkdown(
|
|
`
|
|
1. SVN更新excel文件
|
|
2. 配置Luban(已做可忽略)
|
|
3. 选择**生成类型**,单击生成
|
|
4. 选择要覆盖的文件
|
|
`))
|
|
quesWin.Resize(fyne.NewSize(350, 200))
|
|
quesWin.SetFixedSize(true)
|
|
quesWin.CenterOnScreen()
|
|
quesWin.Show()
|
|
})
|
|
|
|
// layout
|
|
left := container.NewVBox(form, container.NewHBox(&layout.Spacer{}, desBtn, saveBtn, genBtn))
|
|
right := container.NewGridWithColumns(2,
|
|
container.NewBorder(
|
|
container.NewHBox(go_allSelBtn, go_allCancelBtn, go_overrideBtn, widget.NewLabel("Go文件"), this.goList.titleLabel),
|
|
nil, nil, nil,
|
|
this.goList.itemList),
|
|
container.NewBorder(
|
|
container.NewHBox(json_allSelBtn, json_allCancelBtn, json_overrideBtn, widget.NewLabel("Json文件"), this.jsonList.titleLabel),
|
|
nil, nil, nil,
|
|
this.jsonList.itemList))
|
|
|
|
content.Objects = append(content.Objects, container.NewGridWithColumns(2, left, right))
|
|
|
|
this.tabItem.Content = content
|
|
return nil
|
|
}
|
|
|
|
type fileList struct {
|
|
selItemIds []string //选择的ID
|
|
fileTotal int //文件总数
|
|
titleLabel *widget.Label
|
|
cachedList List
|
|
itemList *widget.List
|
|
}
|
|
|
|
func NewFileList() *fileList {
|
|
return &fileList{
|
|
titleLabel: &widget.Label{},
|
|
cachedList: NewList(""),
|
|
}
|
|
}
|
|
|
|
func (f *fileList) createList() *widget.List {
|
|
f.itemList = widget.NewList(
|
|
func() int {
|
|
return len(f.cachedList.Items)
|
|
},
|
|
func() fyne.CanvasObject {
|
|
return widget.NewCheck("Template", func(bool) {})
|
|
},
|
|
func(id widget.ListItemID, item fyne.CanvasObject) {
|
|
c, _ := item.(*widget.Check)
|
|
c.Text = f.cachedList.Items[id].Text
|
|
c.Checked = f.cachedList.Items[id].Checked
|
|
|
|
c.OnChanged = func(b bool) {
|
|
if b {
|
|
f.selItemIds = append(f.selItemIds, c.Text)
|
|
} else {
|
|
f.selItemIds = utils.DeleteString(f.selItemIds, c.Text)
|
|
}
|
|
f.titleLabel.SetText(fmt.Sprintf("(%d/%d)", len(f.selItemIds), f.fileTotal))
|
|
f.cachedList.Items[id].Checked = b
|
|
// sort.Sort(f.cachedList)
|
|
f.itemList.Refresh()
|
|
}
|
|
c.Refresh()
|
|
},
|
|
)
|
|
return f.itemList
|
|
}
|
|
|
|
func (f *fileList) addItem(val string) {
|
|
val = strings.TrimSpace(val)
|
|
if len(val) == 0 {
|
|
return
|
|
}
|
|
newItem := Item{
|
|
Text: val,
|
|
Quantity: 1,
|
|
Checked: true, //默认选中
|
|
}
|
|
f.cachedList.Items = append(f.cachedList.Items, newItem)
|
|
sort.Sort(f.cachedList)
|
|
f.itemList.Refresh()
|
|
}
|
|
|
|
func (f *fileList) deleteItem(name string) {
|
|
for i, v := range f.cachedList.Items {
|
|
if v.Text == name {
|
|
f.selItemIds = utils.DeleteString(f.selItemIds, v.Text)
|
|
f.cachedList.Items = append(f.cachedList.Items[:i], f.cachedList.Items[i+1:]...)
|
|
if f.fileTotal > 0 {
|
|
f.fileTotal--
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 改变列表项目
|
|
func (f *fileList) changeItem(tmpDir, projectDir string) {
|
|
f.fileTotal = 0
|
|
f.selItemIds = []string{}
|
|
f.cachedList = NewList("")
|
|
tmpFiles, err := ioutil.ReadDir(tmpDir)
|
|
if err != nil {
|
|
logrus.Error(err)
|
|
return
|
|
}
|
|
|
|
defer func() {
|
|
if len(tmpFiles) == 0 || len(f.cachedList.Items) == 0 {
|
|
showTip("没有任何变更的文件,请确定SVN拉取最新文件")
|
|
}
|
|
}()
|
|
|
|
projectFiles, err := ioutil.ReadDir(projectDir)
|
|
if err != nil {
|
|
logrus.Error(err)
|
|
return
|
|
}
|
|
|
|
pfMap := make(map[string]int64)
|
|
for _, v := range projectFiles {
|
|
if !v.IsDir() {
|
|
pfMap[v.Name()] = v.ModTime().Unix()
|
|
}
|
|
}
|
|
|
|
for _, file := range tmpFiles {
|
|
if !file.IsDir() {
|
|
if pfTime, ok := pfMap[file.Name()]; ok {
|
|
if file.ModTime().Unix() <= pfTime {
|
|
continue
|
|
}
|
|
}
|
|
f.addItem(file.Name())
|
|
f.selItemIds = append(f.selItemIds, file.Name())
|
|
f.fileTotal++
|
|
logrus.Debugf("%v", file.Name())
|
|
}
|
|
}
|
|
}
|
|
|
|
// 刷新文件数
|
|
func (f *fileList) changeFileCount() {
|
|
f.titleLabel.SetText(fmt.Sprintf("(%d/%d)", len(f.selItemIds), f.fileTotal))
|
|
}
|
|
|
|
func (a *appGen) GetAppName() string {
|
|
return common.TOOLBAR_GEN
|
|
}
|