迁移
This commit is contained in:
parent
8e146aca8b
commit
79a94117a4
75
cmd/bench/base.go
Normal file
75
cmd/bench/base.go
Normal file
@ -0,0 +1,75 @@
|
||||
package bench
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type Target struct {
|
||||
//这里定义需要测试的方法
|
||||
Set func()
|
||||
Get func()
|
||||
}
|
||||
|
||||
//测试基准
|
||||
type Benchmark struct {
|
||||
Parallelism int //并行数目
|
||||
Data interface{} //bench 参数数据
|
||||
TargetBuilder TargetBuilder
|
||||
}
|
||||
|
||||
//构建基准目标
|
||||
type TargetBuilder struct {
|
||||
Name string
|
||||
Make func(bench Benchmark) (Target, error)
|
||||
}
|
||||
|
||||
func compose(parallelisms, dataSize []int, numKeys int, builders []TargetBuilder) []Benchmark {
|
||||
benchmarks := make([]Benchmark, 0, len(parallelisms)*len(dataSize)*len(builders))
|
||||
|
||||
for _, p := range parallelisms {
|
||||
for range dataSize {
|
||||
|
||||
for _, builder := range builders {
|
||||
benchmarks = append(benchmarks, Benchmark{
|
||||
Parallelism: p,
|
||||
// Data: d,
|
||||
TargetBuilder: builder,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return benchmarks
|
||||
}
|
||||
|
||||
func RunBenchmark(b *testing.B, benchmarks []Benchmark) {
|
||||
for _, bench := range benchmarks {
|
||||
bench := bench
|
||||
b.Run(fmt.Sprintf("%s-parallelism(%d)- ", bench.TargetBuilder.Name, bench.Parallelism), func(b *testing.B) {
|
||||
target, err := bench.TargetBuilder.Make(bench)
|
||||
if err != nil {
|
||||
b.Fatalf("%s setup fail: %v", bench.TargetBuilder.Name, err)
|
||||
}
|
||||
if bench.Parallelism == 0 {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
//执行测试方法
|
||||
target.Get()
|
||||
}
|
||||
|
||||
} else {
|
||||
b.SetParallelism(bench.Parallelism) //指定并行数目
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) { //并行执行
|
||||
for pb.Next() {
|
||||
//执行测试方法
|
||||
target.Get()
|
||||
}
|
||||
})
|
||||
}
|
||||
b.StopTimer()
|
||||
})
|
||||
}
|
||||
}
|
71
cmd/bench/main_test.go
Normal file
71
cmd/bench/main_test.go
Normal file
@ -0,0 +1,71 @@
|
||||
package bench
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var LusScriptgetList = `
|
||||
local key = tostring(KEYS[1])
|
||||
local keyss = redis.call("HGETALL", key)
|
||||
local data = {}
|
||||
local n = 1
|
||||
for i, v in ipairs(keyss) do
|
||||
if i%2 == 0 then
|
||||
data[n] = redis.call("HGETALL", v)
|
||||
n = n+1
|
||||
end
|
||||
end
|
||||
return data
|
||||
`
|
||||
var res string
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
defer os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func BenchmarkRedis(b *testing.B) {
|
||||
// uid := "2_62ec8ab8828fb7bf67b220b6"
|
||||
// heroRedisKey := fmt.Sprintf("hero_%s%s", uid, "{herotest}")
|
||||
var (
|
||||
// ncpu = runtime.NumCPU()
|
||||
parallelisms = []int{4, 16, 64}
|
||||
dataSizes = []int{100, 1000, 10000}
|
||||
numKeys = 1024
|
||||
// key = heroRedisKey
|
||||
// keys = []string{
|
||||
// "hero:0_62d6131a3a719b898a90b5fb-62d6131a3a719b898a90b5fe",
|
||||
// "hero:0_62d6131a3a719b898a90b5fb-62d6131a3a719b898a90b600",
|
||||
// "hero:0_62d6131a3a719b898a90b5fb-62d661d6bca6eab554879fc6",
|
||||
// "hero:0_62d6131a3a719b898a90b5fb-62d6694dbca6eab554879fef",
|
||||
// // "hero:0_62bbf14cf88fbd265e61a121-62bbf1849d64e5ee7ff12529",
|
||||
// // "hero:0_62bbf364f88fbd265e61a122-62bbf5189b1970ed6b28b638",
|
||||
// // "hero:0_62bbf364f88fbd265e61a122-62bbf5189b1970ed6b28b63e",
|
||||
// // "hero:0_62bbf57346a32c12466c2e64-62bbf58d9b1970ed6b28b643",
|
||||
// }
|
||||
builders = []TargetBuilder{
|
||||
{
|
||||
Name: "pipeline",
|
||||
Make: func(bench Benchmark) (Target, error) {
|
||||
|
||||
return Target{
|
||||
Get: func() {
|
||||
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "lua",
|
||||
Make: func(bench Benchmark) (Target, error) {
|
||||
return Target{
|
||||
Get: func() {
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
RunBenchmark(b, compose(parallelisms, dataSizes, numKeys, builders))
|
||||
}
|
88
cmd/cmd.go
Normal file
88
cmd/cmd.go
Normal file
@ -0,0 +1,88 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go_dreamfactory/cmd/robot"
|
||||
"go_dreamfactory/pb"
|
||||
"os"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
flag "github.com/spf13/pflag"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func emptyRun(*cobra.Command, []string) {}
|
||||
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "robot",
|
||||
Short: "命令行",
|
||||
Long: "命令行工具",
|
||||
Run: emptyRun,
|
||||
}
|
||||
|
||||
func Execute() {
|
||||
if err := RootCmd.Execute(); err != nil {
|
||||
fmt.Fprintln(os.Stdin, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(runCmd)
|
||||
initLog()
|
||||
robot.InitDb()
|
||||
|
||||
}
|
||||
|
||||
var account = flag.String("account", "", "登录账号")
|
||||
var sid = flag.String("sid", "0", "区服ID")
|
||||
var create = flag.Bool("create", false, "是否创建新账号") //false 不创建新账号
|
||||
var role = flag.Bool("role", false, "创角")
|
||||
|
||||
func CloneNewHero(hero *pb.DBHero) (newHero *pb.DBHero) {
|
||||
newHero = &*hero
|
||||
newHero.Id = primitive.NewObjectID().Hex()
|
||||
|
||||
return
|
||||
}
|
||||
func main() {
|
||||
Execute()
|
||||
}
|
||||
|
||||
var runCmd = &cobra.Command{
|
||||
Use: "run",
|
||||
Short: "启动",
|
||||
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
opts := robot.DefaultOpts()
|
||||
opts.Create = *create
|
||||
opts.Account = *account
|
||||
opts.ServerId = *sid
|
||||
opts.Role = *role
|
||||
r := robot.NewRobot(opts)
|
||||
r.Run()
|
||||
},
|
||||
}
|
||||
|
||||
func initLog() {
|
||||
logrus.New()
|
||||
logrus.SetFormatter(&logrus.TextFormatter{
|
||||
ForceColors: false,
|
||||
FullTimestamp: false,
|
||||
})
|
||||
|
||||
//设置output,默认为stderr,可以为任何io.Writer,比如文件*os.File
|
||||
// file, err := os.OpenFile("robot.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||
// writers := []io.Writer{
|
||||
// file,
|
||||
// os.Stdout}
|
||||
// //同时写文件和屏幕
|
||||
// fileAndStdoutWriter := io.MultiWriter(writers...)
|
||||
// if err == nil {
|
||||
// logrus.SetOutput(fileAndStdoutWriter)
|
||||
// } else {
|
||||
// logrus.Info("failed to log to file.")
|
||||
// }
|
||||
}
|
0
cmd/upgrade/build.sh
Normal file
0
cmd/upgrade/build.sh
Normal file
5
cmd/upgrade/build_linux.bat
Normal file
5
cmd/upgrade/build_linux.bat
Normal file
@ -0,0 +1,5 @@
|
||||
SET CGO_ENABLED=0
|
||||
SET GOOS=linux
|
||||
SET GOARCH=amd64
|
||||
|
||||
go build -o update main.go
|
153
cmd/upgrade/main.go
Normal file
153
cmd/upgrade/main.go
Normal file
@ -0,0 +1,153 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go_dreamfactory/cmd/upgrade/tools"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
//go:embed views/*
|
||||
var f embed.FS
|
||||
|
||||
var version = "0.0.1"
|
||||
|
||||
func main() {
|
||||
|
||||
host := flag.String("host", "10.0.0.9", "Host")
|
||||
port := flag.String("port", "8080", "Port")
|
||||
uploadsDir := flag.String("uploadsDir", "./uploads", "上传文件存储地址")
|
||||
wwwDir := flag.String("wwwDir", "./www", "www服务地址,即解压地址")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
r := gin.Default()
|
||||
r.Static("/prd", "./www")
|
||||
tmpl := template.Must(template.New("").ParseFS(f, "views/*"))
|
||||
r.SetHTMLTemplate(tmpl)
|
||||
|
||||
r.GET("/version", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"version": version,
|
||||
})
|
||||
})
|
||||
|
||||
r.GET("/", func(c *gin.Context) {
|
||||
fmt.Println(tmpl.DefinedTemplates())
|
||||
c.HTML(http.StatusOK, "index.html", nil)
|
||||
})
|
||||
|
||||
r.GET("/upload", func(c *gin.Context) {
|
||||
fmt.Println(tmpl.DefinedTemplates())
|
||||
c.HTML(http.StatusOK, "upload.html", nil)
|
||||
})
|
||||
|
||||
r.POST("/upload", func(c *gin.Context) {
|
||||
f, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
//从上传的文件名获取到版本号
|
||||
s := strings.SplitN(f.Filename, "-", 2)
|
||||
if len(s) != 2 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "上传的文件名中没有包含版本号 eg. update.zip-0.0.1",
|
||||
})
|
||||
return
|
||||
}
|
||||
version = s[1] //设置版本号
|
||||
|
||||
dst := path.Join(*uploadsDir, f.Filename)
|
||||
err = c.SaveUploadedFile(f, dst)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
_, err = tools.Unzip(dst, *wwwDir)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"msg": "upload success",
|
||||
"url": strings.Join([]string{"http://" + *host + ":" + *port, "/prd/", strings.Split(f.Filename, ".")[0], "/index.html"}, ""),
|
||||
})
|
||||
})
|
||||
|
||||
r.GET("/dirs", func(c *gin.Context) {
|
||||
dir, err := ioutil.ReadDir(*wwwDir)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
type Item struct {
|
||||
Name string `json:"name"`
|
||||
Url string `json:"url"`
|
||||
DateTime string `json:"dateTime"`
|
||||
}
|
||||
|
||||
var dirs []Item
|
||||
for _, f := range dir {
|
||||
// if f.IsDir() && len(f.Name()) > 0 && f.Name() != "__MACOSX" {
|
||||
dirs = append(dirs, Item{
|
||||
Name: f.Name(),
|
||||
Url: strings.Join([]string{"http://" + *host + ":" + *port, "/prd/", f.Name()}, ""),
|
||||
DateTime: f.ModTime().Format(time.RFC3339),
|
||||
})
|
||||
// }
|
||||
}
|
||||
|
||||
// 排序
|
||||
sort.SliceStable(dirs, func(i, j int) bool {
|
||||
return dirs[i].DateTime > dirs[j].DateTime
|
||||
})
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"dirs": dirs,
|
||||
})
|
||||
})
|
||||
|
||||
// 同步配置
|
||||
// 接受客户端上传的文件覆盖服务器上文件
|
||||
r.POST("/sync", func(c *gin.Context) {
|
||||
f, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return
|
||||
}
|
||||
if f.Filename!="config.json"{
|
||||
log.Print("上传的配置文件不是config.json")
|
||||
return
|
||||
}
|
||||
dst := path.Join(*wwwDir, f.Filename)
|
||||
err = c.SaveUploadedFile(f, dst)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
err := r.Run("0.0.0.0:" + *port)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
5
cmd/upgrade/readme.md
Normal file
5
cmd/upgrade/readme.md
Normal file
@ -0,0 +1,5 @@
|
||||
解压文件
|
||||
- resources
|
||||
- RobotGUI.exe
|
||||
|
||||
建议覆盖所有文件
|
127
cmd/upgrade/tools/gz.go
Normal file
127
cmd/upgrade/tools/gz.go
Normal file
@ -0,0 +1,127 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func UnGz(tarFile, dest string) error {
|
||||
srcFile, err := os.Open(tarFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer srcFile.Close()
|
||||
gr, err := gzip.NewReader(srcFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer gr.Close()
|
||||
tr := tar.NewReader(gr)
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
filename := dest + hdr.Name
|
||||
file, err := createFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = io.Copy(file, tr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createFile(name string) (*os.File, error) {
|
||||
err := os.MkdirAll(string([]rune(name)[0:strings.LastIndex(name, "/")]), 0755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return os.Create(name)
|
||||
}
|
||||
|
||||
func UnGzip(tarName, xpath string) (err error) {
|
||||
tarFile, err := os.Open(tarName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
err = tarFile.Close()
|
||||
}()
|
||||
|
||||
if err := os.Mkdir(xpath, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
absPath, err := filepath.Abs(xpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tr := tar.NewReader(tarFile)
|
||||
if strings.HasSuffix(tarName, ".gz") || strings.HasSuffix(tarName, ".gzip") {
|
||||
gz, err := gzip.NewReader(tarFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer gz.Close()
|
||||
tr = tar.NewReader(gz)
|
||||
}
|
||||
|
||||
// untar each segment
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// determine proper file path info
|
||||
finfo := hdr.FileInfo()
|
||||
fileName := hdr.Name
|
||||
if filepath.IsAbs(fileName) {
|
||||
fmt.Printf("removing / prefix from %s\n", fileName)
|
||||
fileName, err = filepath.Rel("/", fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
absFileName := filepath.Join(absPath, fileName)
|
||||
|
||||
if finfo.Mode().IsDir() {
|
||||
if err := os.MkdirAll(absFileName, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// create new file with original file mode
|
||||
file, err := os.OpenFile(absFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, finfo.Mode().Perm())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("x %s\n", absFileName)
|
||||
n, cpErr := io.Copy(file, tr)
|
||||
if closeErr := file.Close(); closeErr != nil { // close file immediately
|
||||
return err
|
||||
}
|
||||
if cpErr != nil {
|
||||
return cpErr
|
||||
}
|
||||
if n != finfo.Size() {
|
||||
return fmt.Errorf("unexpected bytes written: wrote %d, want %d", n, finfo.Size())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
56
cmd/upgrade/tools/zip.go
Normal file
56
cmd/upgrade/tools/zip.go
Normal file
@ -0,0 +1,56 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Unzip(src string, dest string) ([]string, error) {
|
||||
var filenames []string
|
||||
r, err := zip.OpenReader(src)
|
||||
if err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
for _, f := range r.File {
|
||||
// Store filename/path for returning and using later on
|
||||
fpath := filepath.Join(dest, f.Name)
|
||||
// Check for ZipSlip. More Info: http://bit.ly/2MsjAWE
|
||||
if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
|
||||
return filenames, fmt.Errorf("%s: illegal file path", fpath)
|
||||
}
|
||||
filenames = append(filenames, fpath)
|
||||
if f.FileInfo().IsDir() {
|
||||
// Make Folder
|
||||
if err := os.MkdirAll(fpath, os.ModePerm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
// Make File
|
||||
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
||||
if err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
_, err = io.Copy(outFile, rc)
|
||||
// Close the file without defer to close before next iteration of loop
|
||||
outFile.Close()
|
||||
rc.Close()
|
||||
if err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
}
|
||||
return filenames, nil
|
||||
}
|
55
cmd/upgrade/views/index.html
Normal file
55
cmd/upgrade/views/index.html
Normal file
@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>下载更新包</title>
|
||||
<!-- import Vue.js -->
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.6/vue.min.js"></script>
|
||||
<!-- import stylesheet -->
|
||||
<link href="https://cdn.bootcdn.net/ajax/libs/iview/3.5.5-rc.1/styles/iview.min.css" rel="stylesheet">
|
||||
<!-- import iView -->
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/iview/3.5.5-rc.1/iview.min.js"></script>
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
|
||||
<style>
|
||||
#app {
|
||||
margin: 20px 40px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<h1>下载更新包</h1>
|
||||
|
||||
<strong>历史prd:</strong>
|
||||
<br><br>
|
||||
<list border>
|
||||
<list-item v-for="dir in dirs">
|
||||
<a :href="dir.url" target="_blank">${ dir.name }</a> <span>${ dir.dateTime}</span>
|
||||
</list-item>
|
||||
</list>
|
||||
</div>
|
||||
<script>
|
||||
new Vue({
|
||||
el: "#app",
|
||||
delimiters: ['${', '}'],
|
||||
data: {
|
||||
zips: [],
|
||||
dirs: [],
|
||||
},
|
||||
methods: {
|
||||
handleSuccess(response, file, fileList) {
|
||||
this.zips.push(response.url)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
axios.get("/dirs").then((res) => {
|
||||
this.dirs = res.data.dirs
|
||||
})
|
||||
},
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
69
cmd/upgrade/views/upload.html
Normal file
69
cmd/upgrade/views/upload.html
Normal file
@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>上传</title>
|
||||
<!-- import Vue.js -->
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.6/vue.min.js"></script>
|
||||
<!-- import stylesheet -->
|
||||
<link href="https://cdn.bootcdn.net/ajax/libs/iview/3.5.5-rc.1/styles/iview.min.css" rel="stylesheet">
|
||||
<!-- import iView -->
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/iview/3.5.5-rc.1/iview.min.js"></script>
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
|
||||
<style>
|
||||
#app {
|
||||
margin: 20px 40px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
|
||||
<h1>上传文件</h1>
|
||||
|
||||
<upload type="drag" action="/upload" paste="true" accept=".zip" :on-success="handleSuccess">
|
||||
<div style="padding: 20px 0">
|
||||
<icon type="ios-cloud-upload" size="52" style="color: #3399ff"></icon>
|
||||
<p>点击或者拖拽上传</p>
|
||||
</div>
|
||||
</upload>
|
||||
|
||||
<alert type="success" v-for="url in zips">
|
||||
浏览地址:${ url }
|
||||
</alert>
|
||||
|
||||
|
||||
|
||||
<strong>历史prd:</strong>
|
||||
<br><br>
|
||||
<list border>
|
||||
<list-item v-for="dir in dirs">
|
||||
<a :href="dir.url" target="_blank">${ dir.name }</a> <span>${ dir.dateTime}</span>
|
||||
</list-item>
|
||||
</list>
|
||||
</div>
|
||||
<script>
|
||||
new Vue({
|
||||
el: "#app",
|
||||
delimiters: ['${', '}'],
|
||||
data: {
|
||||
zips: [],
|
||||
dirs: [],
|
||||
},
|
||||
methods: {
|
||||
handleSuccess(response, file, fileList) {
|
||||
this.zips.push(response.url)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
axios.get("/dirs").then((res) => {
|
||||
this.dirs = res.data.dirs
|
||||
})
|
||||
},
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
BIN
cmd/v2/.DS_Store
vendored
Normal file
BIN
cmd/v2/.DS_Store
vendored
Normal file
Binary file not shown.
719
cmd/v2/.cache.meta
Normal file
719
cmd/v2/.cache.meta
Normal file
@ -0,0 +1,719 @@
|
||||
c:/tmp/go/Game.ActiveReward.go,2A4C58CF623C66F5DAE5EED5FA3B2FC,1264,1675761410251
|
||||
c:/tmp/go/Game.ActiveRewardData.go,BB5CFACC5905463C958AD4DC4260E0,2482,1682218335291
|
||||
c:/tmp/go/Game.ArenaActiveReward.go,CF58C256CADAF3D5679205973F1BE,1340,1675761410246
|
||||
c:/tmp/go/Game.ArenaActiveRewardData.go,AB854D4D4EEA6498469BD7D92864B6D,3190,1675761410197
|
||||
c:/tmp/go/Game.ArenaBuyChallenge.go,9758AC77DCC231E389792F729123157,1339,1675761410269
|
||||
c:/tmp/go/Game.ArenaBuyChallengeData.go,C92E3D28BAB432704E72DB8C5131C6,1802,1675761410208
|
||||
c:/tmp/go/Game.ArenaChallengeNpc.go,FF10972C6BB39C5C22CFCBE0E5D05721,1338,1675761410246
|
||||
c:/tmp/go/Game.ArenaChallengeNpcData.go,DEE170B4F368857A646E7FB44B65506D,4951,1675761410221
|
||||
c:/tmp/go/Game.ArenaRankReward.go,4BE39C4E12E8C6A1515ED7A8B378D50,1308,1675761410269
|
||||
c:/tmp/go/Game.ArenaRankRewardData.go,5F8C9ED0253F3520D040964E6D712031,2214,1675761410208
|
||||
c:/tmp/go/Game.ArenaRobot.go,CAED277469FA633986FCF6ABBE856F,1233,1675761410257
|
||||
c:/tmp/go/Game.ArenaRobotData.go,7E1D4424304D904C40B88D9326BE1C0,1660,1675761410235
|
||||
c:/tmp/go/Game.atn.go,C139B84B8BFE3221FCB10871B501C9E,1210,1675761410265
|
||||
c:/tmp/go/Game.atr.go,7F6D48BC9BB4FA17FA1CA6493E7EC819,1092,1675761410196
|
||||
c:/tmp/go/Game.basepool.go,C52EBBAE85F780685FB93393A86DD150,1294,1675761410253
|
||||
c:/tmp/go/Game.Battleready_capskill.go,63C11EEAA389EBE8F61FE47A98EB2A,1383,1677038179630
|
||||
c:/tmp/go/Game.Battleready_capskillData.go,E3159601E87988D15E95DC2389ECC7,4140,1677038179616
|
||||
c:/tmp/go/Game.BattleReady.go,FBE5ACCFC2CDEDEF25554260BAB2EA,1248,1675761410230
|
||||
c:/tmp/go/Game.BattleReadyData.go,9DB84583F363DA80CCF171959D82E85F,4495,1681962385973
|
||||
c:/tmp/go/Game.Battletasktesting.go,54449FABECEBEE4B2082B27C7C4B5D0,1338,1675761410254
|
||||
c:/tmp/go/Game.BattletasktestingData.go,359E55381E658F6379283E7D21B28966,1809,1675761410193
|
||||
c:/tmp/go/Game.Breakingbad.go,B5A342ABAFD95367B37133A471AAB418,1260,1679653220443
|
||||
c:/tmp/go/Game.BreakingbadData.go,8990C42A561478ABAF2AA6D6260C1C2,2391,1679653220443
|
||||
c:/tmp/go/Game.BreakingbadTag.go,8BD327BF28CD5F22594410B71D16775C,1295,1680144063080
|
||||
c:/tmp/go/Game.BreakingbadTagData.go,4CC6B5F571FDD6B971B4257844ABD,1533,1680144063054
|
||||
c:/tmp/go/Game.BubbleGroup.go,2F534939A578E993A553CBAAE4AA34F,1251,1677661885207
|
||||
c:/tmp/go/Game.BubbleGroupData.go,4B36BAC583FCC6CB42627A3FA41F73D,2500,1677661885207
|
||||
c:/tmp/go/Game.BuffType.go,84A8B77D2EDE5F4FDE950EF8EBA4155,4133,1677729194807
|
||||
c:/tmp/go/Game.BuzkashiFm.go,9790C180543996CD9FBBAC6EC98A8E4A,1234,1682218335288
|
||||
c:/tmp/go/Game.BuzkashiFmData.go,6AD1B6C2D21BFADEE74C2F04152C0C,1956,1682218335303
|
||||
c:/tmp/go/Game.BuzkashiGrade.go,2A399692DCDB394ABCFEF628847CDB4,1279,1682057107480
|
||||
c:/tmp/go/Game.BuzkashiGradeData.go,57E858BEE143A2ED19ADA7F4FA30E6D5,1411,1682057107480
|
||||
c:/tmp/go/Game.BuzkashiLv.go,82902BAD1533FCB6B0EB97BE2DD4C150,1234,1682057107465
|
||||
c:/tmp/go/Game.BuzkashiLvData.go,EDDCFE57F22837BC75647ECC1F956A,1380,1682057107465
|
||||
c:/tmp/go/Game.BuzkashiMount.go,D4EB7944C4C9CBB728B516AC9419D244,1282,1682307537253
|
||||
c:/tmp/go/Game.BuzkashiMountData.go,D5896D807CD943ED184CCFE4DA2AD3,4273,1682318037405
|
||||
c:/tmp/go/Game.BuzkashiOpen.go,5EB177235A1849D0F77BCE291C829BF,1264,1682218335288
|
||||
c:/tmp/go/Game.BuzkashiOpenData.go,B0B0232A7494B1DC1984E8E32974D2,1833,1682218335277
|
||||
c:/tmp/go/Game.BuzkashiReward.go,3BB3D18DCB94ED9F68C15F643BD8A0,1294,1682057107465
|
||||
c:/tmp/go/Game.BuzkashiRewardData.go,B0F347899D71E47ECD47F24B71F124EA,1994,1682057107465
|
||||
c:/tmp/go/Game.CampLv.go,B2F720E6C77B16377AB520BE2C7545C1,1173,1681962385984
|
||||
c:/tmp/go/Game.CampLvData.go,BF3E5CF18079FE516E7B2659E006124,1912,1681962385964
|
||||
c:/tmp/go/Game.ChatChannel.go,255A77714FAE1CF5DE6C14811358D470,1253,1675761410251
|
||||
c:/tmp/go/Game.ChatChannelCom.go,5D2A2CD37069567DB414AB168E14E5,1298,1675761410262
|
||||
c:/tmp/go/Game.ChatChannelComData.go,F3FFCBC678324620AFE76EC48513127,1345,1675761410239
|
||||
c:/tmp/go/Game.ChatChannelData.go,7F2F68195692654A592631423EFE6492,1405,1675761410239
|
||||
c:/tmp/go/Game.ChatExpression.go,8242E791111470685E76F7EDDAA7EAAD,1294,1675761410201
|
||||
c:/tmp/go/Game.ChatExpressionData.go,85E4E397338D9FD291FEA997FEF42,1652,1675761410212
|
||||
c:/tmp/go/Game.ChatServerGroup.go,6FC9A7446A5EF694AA15EEA56D71D35,1316,1675761410226
|
||||
c:/tmp/go/Game.ChatServerGroupData.go,FD99FB68BD87CF1F16F64D6CC0CE662A,1236,1675761410250
|
||||
c:/tmp/go/Game.ChatSystem.go,9C4C28E7F89D15A1C840DB755B2413,1234,1675761410202
|
||||
c:/tmp/go/Game.ChatSystemData.go,1D24C9D746E6BE586CA4DC5CEE6DC6FF,3364,1675761410274
|
||||
c:/tmp/go/Game.ChildSkills.go,922FAC4CD0961B9B224588026ED83F4,1458,1675761410253
|
||||
c:/tmp/go/Game.Coin.go,1349FF95D707E6BCC34A264A4372B3,1148,1675761410201
|
||||
c:/tmp/go/Game.CoinData.go,744923CD8CC8DC38BCD9D3BC67EE9D44,2468,1681972759520
|
||||
c:/tmp/go/Game.CombatBox.go,42667B2BA872367DCECE7B5D267016E0,1218,1675761410205
|
||||
c:/tmp/go/Game.CombatBoxData.go,8DC5435952D1A5AB3F838B0A2214DE,1229,1675761410230
|
||||
c:/tmp/go/Game.CombatLevel.go,BB32B0B37B213A73B7BDC2422EBE1346,1248,1675761410255
|
||||
c:/tmp/go/Game.CombatLevelData.go,8A9978FE96CDD87A50591CDD351F82B3,3688,1675761410219
|
||||
c:/tmp/go/Game.CombatManster.go,1A12286B5065733FFB364BE056514BFE,1278,1675761410193
|
||||
c:/tmp/go/Game.CombatMansterData.go,99D045C7EAA67D227912D4A952E0385F,3870,1675761410243
|
||||
c:/tmp/go/Game.Dispatch_Battle.go,EF269EDA2AB24187FE3AC87FE5EE32D7,1308,1677038179621
|
||||
c:/tmp/go/Game.Dispatch_BattleData.go,497F218955C1B5DED2BB218C574EE344,6642,1681962385984
|
||||
c:/tmp/go/Game.Dispatch_Lv.go,9B254F9CB7ED221D8151B8FF50DAC247,1248,1677038179627
|
||||
c:/tmp/go/Game.Dispatch_LvData.go,6FFDB8723372C64B667793344EFAE59D,1908,1677142535210
|
||||
c:/tmp/go/Game.Dispatch_Task.go,5CEBAC2124C0ED2BE09DEEACC48385F3,1278,1677038179618
|
||||
c:/tmp/go/Game.Dispatch_TaskData.go,F29B6EB9785BA34686F61C8AA6E641,6972,1677661885207
|
||||
c:/tmp/go/Game.dispatch.go,11E6C4EF7C33F3DCC5EECFD532ADFB1,1687,1677123193278
|
||||
c:/tmp/go/Game.DispatchCond.go,22356882B4901B94B186849B43A,1230,1677226965191
|
||||
c:/tmp/go/Game.DispatchCondType.go,1E174CC34C6D73C2A42D268158D36,444,1677226965193
|
||||
c:/tmp/go/Game.DrawCard.go,90C51587F78BB9A35B5606965AA5D5C,1204,1675761410276
|
||||
c:/tmp/go/Game.DrawCardData.go,8E5E5CA24F2F804AEDF7FA2D75EC768,2117,1681962385979
|
||||
c:/tmp/go/Game.DreamlandBoos.go,ECAB104849265818FC51EFE3A85C7E92,1286,1675761410199
|
||||
c:/tmp/go/Game.DreamlandBoosData.go,A558CD5CA0D1669B44CE1D0D55A4CA9,4883,1675761410210
|
||||
c:/tmp/go/Game.DreamlandChallenge.go,E82C6BF569667EC9D353D2CFA68189A,1357,1675761410260
|
||||
c:/tmp/go/Game.DreamlandChallengeData.go,D96E1D6267907A798D67399A5D81EFC,1821,1675761410223
|
||||
c:/tmp/go/Game.DreamlandTrigger.go,9E9F37FA9CCB7EE2F4E25D3EB77B6D8A,1323,1675761410271
|
||||
c:/tmp/go/Game.DreamlandTriggerData.go,952970A66BEC2297B5D574F2CBB1217F,1440,1675761410237
|
||||
c:/tmp/go/Game.Drop.go,55BD3930367DDA4F886A27283A66EBD6,1143,1675761410211
|
||||
c:/tmp/go/Game.DropData.go,3342529A163A3B8DD13D138AD08E5E3C,2461,1677661885222
|
||||
c:/tmp/go/Game.EnchantBoss.go,4D46566E197D16B45C27B81E94AB8A3A,1248,1675761410193
|
||||
c:/tmp/go/Game.EnchantBossData.go,BD3D794251FA272228B19321CDD719,9255,1675761410243
|
||||
c:/tmp/go/Game.EnchantLineup.go,D4B91419B79DFDC473AFA76B05DD382,1278,1675761410230
|
||||
c:/tmp/go/Game.EnchantLineupData.go,1DD1C2ED36E6D5E14524C5B72094B7,1775,1675761410265
|
||||
c:/tmp/go/Game.EnchantShop.go,AA2D17324C32244E4F2E1BDE85F65,1252,1675761410266
|
||||
c:/tmp/go/Game.EnchantShopData.go,53DB80733785154E652F424E37F44875,1772,1675761410218
|
||||
c:/tmp/go/Game.Equip.go,9C164DE97A449B535FDC6D15675988,1162,1675761410242
|
||||
c:/tmp/go/Game.EquipAttribute.go,1A45B554B4BECF3E713FD0794DE79A63,1298,1675761410251
|
||||
c:/tmp/go/Game.EquipAttributeData.go,FED91140C4D297AC1071D1EE92995730,2820,1675761410242
|
||||
c:/tmp/go/Game.EquipAttrlibrary.go,39CECBB16F43FC2DCDDE5C188AA7ABF7,1066,1678261258950
|
||||
c:/tmp/go/Game.EquipAttrlibraryData.go,7CE1BE10931D026525AF13B3B8885C,2712,1675761410228
|
||||
c:/tmp/go/Game.EquipColor.go,BEEF34ED81AE1D6EA3574E82F7186E6,1234,1675761410215
|
||||
c:/tmp/go/Game.EquipColorData.go,B9AE164A7F18CFF047CB69C8C8AE32C3,1493,1675761410251
|
||||
c:/tmp/go/Game.EquipData.go,2930CDCB6C39ECCF4857D4678E40BDB,6752,1677038179623
|
||||
c:/tmp/go/Game.EquipEnchanting.go,92448D8E82F4BAE26C7C60EFA3B3B283,1314,1675761410263
|
||||
c:/tmp/go/Game.EquipEnchantingData.go,77D3D341E3AD3E17C335C29FC13AD5,2478,1675761410203
|
||||
c:/tmp/go/Game.EquipIntensify.go,285189CB91B06B7F53153B8F265BD7,1294,1675761410263
|
||||
c:/tmp/go/Game.EquipIntensifyData.go,45F342D7A6FDF510FF515F64FBF1FFB,3073,1675761410227
|
||||
c:/tmp/go/Game.EquipPos.go,AAAF6EA38990FF3DDAC7BCEF5ADC633D,1204,1675761410262
|
||||
c:/tmp/go/Game.EquipPosData.go,1E63B156CBCFB20E8C691898AE25E6,2446,1675761410273
|
||||
c:/tmp/go/Game.EquipSCompose.go,C7236D5F82A62C8CD3F4F6174B4E1E,1279,1675761410203
|
||||
c:/tmp/go/Game.EquipSComposeData.go,B312B57FDEF5EDA145844FC9668DBDA1,3957,1675761410214
|
||||
c:/tmp/go/Game.EquipSuit.go,1DBACFCC95AB7D3A0774E47C6E641D,1224,1675761410204
|
||||
c:/tmp/go/Game.EquipSuitData.go,B7ABBAA106A3AA297CF2C7DABBFA5C,3592,1680333520466
|
||||
c:/tmp/go/Game.Extservers.go,24E68E3B8FFC59B781DA294CC3F5847B,1236,1675761410243
|
||||
c:/tmp/go/Game.ExtserversData.go,52249AAE1D2EB94DCB6A9288D84A2B9,1871,1675761410229
|
||||
c:/tmp/go/Game.Facemod.go,696B7D4AC948AA8271077188397D428,1188,1675761410212
|
||||
c:/tmp/go/Game.FacemodData.go,30AEF98DBD79A51C4A93E741AED26D,1896,1675761410250
|
||||
c:/tmp/go/Game.Favorability.go,3C2511F6F1D0FB53AE57B2DA87B5572B,1022,1682307537247
|
||||
c:/tmp/go/Game.FavorabilityData.go,4865A5619D22F92254EF6316DD6999B6,13476,1682218335290
|
||||
c:/tmp/go/Game.FightEventType.go,3764E69F8E6A6D457FE301131809B54,1449,1675761410242
|
||||
c:/tmp/go/Game.FightGlobalEvent.go,409C726DCE4AA9B8A52CE7DA1B72354,1323,1675761410195
|
||||
c:/tmp/go/Game.FightGlobalEventData.go,F9E56770C69839536E63381F269E576D,4409,1675761410219
|
||||
c:/tmp/go/Game.Figure.go,9FBAAA6E489C6C9B11B813D8420E4C,2169,1675761410261
|
||||
c:/tmp/go/Game.Friends.go,7790A592B6D3BEE53FF6FC37E8C7EE32,1188,1681962385984
|
||||
c:/tmp/go/Game.FriendsData.go,6C2799F690B9F11A2292057D064AE83,4189,1681962385973
|
||||
c:/tmp/go/Game.GetResource.go,16426C584C734CACBB6BED9BA5881A3B,1248,1675761410210
|
||||
c:/tmp/go/Game.GetResourceData.go,1E11E21D4B3297D66567FD6CF7A091F9,1755,1675761410248
|
||||
c:/tmp/go/Game.Global.go,9092173F7DF6CF18DC2D1FD0B2BEE8A,1178,1675761410253
|
||||
c:/tmp/go/Game.GlobalData.go,B39DE084445A86E113701F5D44949,69195,1682307537195
|
||||
c:/tmp/go/Game.GM.go,A5074D93B98C124CEFBD8F73178EC8,1113,1675761410219
|
||||
c:/tmp/go/Game.GMData.go,604CF1227DE557E0D48AB86C3396A3,1878,1675761410193
|
||||
c:/tmp/go/Game.Gourmet.go,CA1C778A379332C0716D30561658D7B,967,1675761410238
|
||||
c:/tmp/go/Game.GourmetData.go,A9A7BB74770AAD806766E1EDD2B8C,8164,1675761410200
|
||||
c:/tmp/go/Game.GrowReward.go,2A925988749D11CAB754A7E581FED53C,1235,1675761410232
|
||||
c:/tmp/go/Game.GrowRewardData.go,EEACB4D8C0C845AF1C3C428B65A84833,2221,1675761410221
|
||||
c:/tmp/go/Game.GrowTask.go,7244F62F6FB0BCD7FCC5CCC5A7CA24B7,1203,1675761410256
|
||||
c:/tmp/go/Game.GrowTaskData.go,CA5515AD797579648B663BD0D40F6BB,3505,1675761410195
|
||||
c:/tmp/go/Game.Guide.go,933A9C98166249698370EEA9183E44D0,1158,1675761410243
|
||||
c:/tmp/go/Game.GuideData.go,492888C8E3BA62ED8FA49BDA6DF25D23,7402,1675761410205
|
||||
c:/tmp/go/Game.GuildActivity.go,AC5BBC11BECD9EA038561EA593F2881C,1278,1675761410222
|
||||
c:/tmp/go/Game.GuildActivityData.go,0A54FE4126E57ADBD33A52BD3937B6,1981,1675761410233
|
||||
c:/tmp/go/Game.GuildBossTask.go,F58CAEDEC61D4C38AFA8A3261FEA3DC,1278,1675761410256
|
||||
c:/tmp/go/Game.GuildBossTaskData.go,28AB24D1DF646E94979351F6E4BDF7,2434,1675761410221
|
||||
c:/tmp/go/Game.GuildLv.go,D3E86616C1644AE037FB22E322DD81DC,1188,1675761410245
|
||||
c:/tmp/go/Game.GuildLvData.go,F19B2E8B4383F9C2C923EEF38D4AFADE,1414,1675761410207
|
||||
c:/tmp/go/Game.GuildPng.go,9679AD4D302E32CBD2E9DF68BB1CE2D,1203,1675761410196
|
||||
c:/tmp/go/Game.GuildPngData.go,B28B7B9C99F4D6E3CB60E24EB76EA644,1165,1675761410256
|
||||
c:/tmp/go/Game.GuildSign.go,FDDA8A37B478D1D443A25E107457FC,1218,1675761410269
|
||||
c:/tmp/go/Game.GuildSignData.go,697B162D3BEF3014F416838B1FE731,2805,1675761410245
|
||||
c:/tmp/go/Game.GuildTask.go,61C5DF09B39879C8A483F2D12422643,1222,1675761410207
|
||||
c:/tmp/go/Game.GuildTaskData.go,3EC4EFACCAB29A882D465EB9C48CF4C,3612,1675761410197
|
||||
c:/tmp/go/Game.Help.go,A94E51B9F7ABAA87547443672CB923B,1148,1675761410255
|
||||
c:/tmp/go/Game.HelpData.go,267EF0A8DCD0656589654CD0ADCDA580,1826,1675761410267
|
||||
c:/tmp/go/Game.Hero.go,E07FC7E26518CE4886779D4528CD9C74,1148,1675761410228
|
||||
c:/tmp/go/Game.HeroAwaken.go,C0DB8169DEA54CA5D19A5FB43FCC3E,1000,1675761410240
|
||||
c:/tmp/go/Game.HeroAwakenData.go,37CD89396C7A693B61AC307EE3A64AD0,3753,1675761410263
|
||||
c:/tmp/go/Game.HeroConvertdata.go,9F2AB5796FC99EB98165B2CAB35C2FD,1310,1675761410209
|
||||
c:/tmp/go/Game.HeroConvertdataData.go,2B3B3695CDE3256E121D762D26CCE83,1220,1675761410270
|
||||
c:/tmp/go/Game.HeroData.go,319137D6E9D359F412E169F5FAB83F3D,11635,1678157698141
|
||||
c:/tmp/go/Game.HeroExp.go,A385FC37766A4642A24DEC24345AA2,1196,1675761410264
|
||||
c:/tmp/go/Game.HeroExpData.go,AEB319CEE85EBFFEDCFBE484C3393D5,1375,1675761410228
|
||||
c:/tmp/go/Game.Herofusion.go,5E9BC88C372F2CB0E3D95AFD327D64B,1239,1675761410222
|
||||
c:/tmp/go/Game.HerofusionData.go,D66C2D2316D2B4E7E1B7ABA476136,3056,1675761410208
|
||||
c:/tmp/go/Game.HeroLevelgrow.go,62F860BC46B98EE3D4CF7C1388F99696,1282,1675761410217
|
||||
c:/tmp/go/Game.HeroLevelgrowData.go,37140A53ED2B4B3FE94293F87EA4D30,3285,1675761410228
|
||||
c:/tmp/go/Game.HeroLevelup.go,3F2BECF97236DD798F0B08F546272B5,1251,1675761410203
|
||||
c:/tmp/go/Game.HeroLevelupData.go,3D4339CCF262D4D3EC71E7031DA8D84,1810,1675761410215
|
||||
c:/tmp/go/Game.HeroMethod.go,AB325C916459C45B86A355E196384FB,1238,1675761410276
|
||||
c:/tmp/go/Game.HeroMethodComment.go,86ACB82FD48C164AF871DD482C5C3412,1338,1675761410251
|
||||
c:/tmp/go/Game.HeroMethodCommentData.go,E821B41420AE45BF1D59E3CC8AAA0,1542,1675761410240
|
||||
c:/tmp/go/Game.HeroMethodData.go,4B2248B2BB54E0B6573D3E321CBB559B,3952,1675761410203
|
||||
c:/tmp/go/Game.HeroSkill.go,DAE82818874931F13EA6E49E16E57AF,1220,1675761410216
|
||||
c:/tmp/go/Game.HeroSkillData.go,446DD726A7453FFEFADCDD574ECC73,1774,1675761410252
|
||||
c:/tmp/go/Game.HeroSkillLevel.go,8D2859A0BBCA17996549BA564FB01422,1293,1675761410251
|
||||
c:/tmp/go/Game.HeroSkillLevelData.go,C5B9DC433F5E27C27D52BCC6DEDA049,1736,1675761410214
|
||||
c:/tmp/go/Game.HeroStargrow.go,492BA607A1884D4EBB49E7E6C4C854E,1265,1675761410242
|
||||
c:/tmp/go/Game.HeroStargrowData.go,6019EAC8CE1372867D90F89E2ED94164,2301,1675761410253
|
||||
c:/tmp/go/Game.HeroStarup.go,92EB8FF34029EB6419A1765AAB86E81E,1000,1675761410264
|
||||
c:/tmp/go/Game.HeroStarupData.go,A4793267B362932A5331AA2129FBFF,2792,1675761410242
|
||||
c:/tmp/go/Game.HeroStrategy.go,9973410C0D9C081EDD1D4452374B6F,1271,1675761410255
|
||||
c:/tmp/go/Game.HeroStrategyData.go,A9CA8CB14D58884C5AD37839F7FF81,3868,1680513216864
|
||||
c:/tmp/go/Game.HeroTalent.go,6264DCAF544AB03B831FB59DF3F8FCC9,1233,1675761410198
|
||||
c:/tmp/go/Game.HeroTalentData.go,749A96D22062A710628DFA198A59D529,3586,1675761410258
|
||||
c:/tmp/go/Game.Horoscope.go,BDF321486A49AE5AB0BA1316EF15DBF0,1218,1675761410256
|
||||
c:/tmp/go/Game.HoroscopeData.go,79433F42E8E9E55A7D1C0B5C32DDE55,5694,1675761410244
|
||||
c:/tmp/go/Game.HuntingBoss.go,311D49EDF068E84BB17F994BC7EB1CE3,1011,1675761410248
|
||||
c:/tmp/go/Game.HuntingBossData.go,A9D97FD4F8A1A9757ADD536113C0B77F,5976,1675761410200
|
||||
c:/tmp/go/Game.HuntingChallenge.go,3AD58AB0168FFF7380D819F1E72BDD9B,1327,1675761410260
|
||||
c:/tmp/go/Game.HuntingChallengeData.go,77A35BF882453D69A9F6326134E7788,1807,1675761410223
|
||||
c:/tmp/go/Game.HuntingLineup.go,62EEE3FDB904063CA62AA475655A59,1278,1675761410210
|
||||
c:/tmp/go/Game.HuntingLineupData.go,9019AF4B463FDB893041DF5BBC4B1011,1661,1675761410248
|
||||
c:/tmp/go/Game.HuntingOpenTime.go,96F7469AD2F779F3FE69D69D90D32047,1310,1675761410271
|
||||
c:/tmp/go/Game.HuntingOpenTimeData.go,331AE9F326C5ED6E8C5531DA55B31D,3197,1675761410237
|
||||
c:/tmp/go/Game.Initial.go,635F41467132462445C61D22F4DBC899,1195,1675761410226
|
||||
c:/tmp/go/Game.InitialData.go,2EB61924191FD8F08B66BB694A60342C,1681,1675761410213
|
||||
c:/tmp/go/Game.Item.go,AD5F8B4F3FE72A282CA629AA2E85,1147,1675761410276
|
||||
c:/tmp/go/Game.ItemBox.go,A96F4F987C964A2E18D6C4D1A1ADFB2,1196,1675761410196
|
||||
c:/tmp/go/Game.ItemBoxData.go,BBB7D95490F3598D3CA444B72E3ACA,1135,1675761410257
|
||||
c:/tmp/go/Game.ItemData.go,D9A2C8C91228307D2DECFCD42D005,7136,1681962385973
|
||||
c:/tmp/go/Game.itinerant_city.go,521EA56852E953C5F91CA8AEADFD28F,1293,1681962385972
|
||||
c:/tmp/go/Game.itinerant_cityData.go,21EBB2968FA58C3F5845E35680E8BD,5825,1681962386033
|
||||
c:/tmp/go/Game.itinerant_lv.go,3594774D51FD4B7FF946B9B408E2390,1263,1681962385982
|
||||
c:/tmp/go/Game.itinerant_lvData.go,88612F1C5A87E9E9C4AAEE78A91AB4E3,1986,1681962385972
|
||||
c:/tmp/go/Game.itinerant_reward.go,99ACE7B84ACFB49B674712DF97997FC,1324,1681962385986
|
||||
c:/tmp/go/Game.itinerant_rewardData.go,558B40F8C45748ED19431A7445047D,1807,1681962385972
|
||||
c:/tmp/go/Game.itinerant_thing.go,9C6A37B7E6F93A7B2615AF5D828865,1308,1681962385979
|
||||
c:/tmp/go/Game.itinerant_thingData.go,88B75FA60CEF81CB351438913278C,6680,1681962385978
|
||||
c:/tmp/go/Game.kv.go,FD719127588B2570CA6C764B5A3BBA1F,1136,1682307537148
|
||||
c:/tmp/go/Game.LibraryBubble.go,F8A001DE17E77B4DE7E079BADE41,1278,1675761410259
|
||||
c:/tmp/go/Game.LibraryBubbleData.go,F762FCF378AA30E8B8A1CFB4F8A939B,1500,1675761410198
|
||||
c:/tmp/go/Game.LibraryComplot.go,E44641F1682F8527A599D29EE6EE,1293,1675761410198
|
||||
c:/tmp/go/Game.LibraryComplotData.go,FDD21B3B8EFA299D4E3FDFB58ECFD,3202,1675761410223
|
||||
c:/tmp/go/Game.LibraryFavor.go,2A34F748C8379E7A8E65E4FA3998D6,1022,1675761410236
|
||||
c:/tmp/go/Game.LibraryFavorData.go,55848D72E7E9DA1738B55AD22A244,2340,1675761410209
|
||||
c:/tmp/go/Game.LibraryFavorlv.go,19BDF396B7D0B5DEB62463385B16A843,1298,1675761410270
|
||||
c:/tmp/go/Game.LibraryFavorlvData.go,33D02C16A23575FA26138B6AEF501139,1657,1675761410246
|
||||
c:/tmp/go/Game.LibraryFetter.go,A1355BDA3FF33B8E21EB36D33A87E4C,1033,1675761410271
|
||||
c:/tmp/go/Game.LibraryFetterData.go,531A8A4177861CAE4748064FCEB8D6,4075,1675761410209
|
||||
c:/tmp/go/Game.LibraryHero.go,34F04069AD3E532A816C917AC25E182,1253,1675761410236
|
||||
c:/tmp/go/Game.LibraryHeroData.go,EBB061E65F995B9385D5913BCFA614,6618,1675761410248
|
||||
c:/tmp/go/Game.LibraryHistory.go,1F1A3EA6E45ACA8D3D1F5CFB8922CDE,1302,1675761410270
|
||||
c:/tmp/go/Game.LibraryHistoryData.go,CEA74480729040961747BF5269171DE,2606,1675761410259
|
||||
c:/tmp/go/Game.LibraryPlayBack.go,2F69CE6BDF33ED16DB93F143AEA422E,1313,1675761410236
|
||||
c:/tmp/go/Game.LibraryPlayBackData.go,C0644CB6407125B96347987FD288A6,2044,1675761410210
|
||||
c:/tmp/go/Game.LibraryStory.go,9A7987EB27ECC6D4A141BDC50405FF4,1264,1675761410199
|
||||
c:/tmp/go/Game.LibraryStoryData.go,FD3A637B4D396CEA1F78939886DA210,1960,1675761410223
|
||||
c:/tmp/go/Game.LinestoryMainTask.go,D1A9F77A18E8A617DF04E16534894F4,1338,1675761410198
|
||||
c:/tmp/go/Game.LinestoryMainTaskData.go,2C92B7BB4303061573012BB2E0A4A,3645,1682318038099
|
||||
c:/tmp/go/Game.LinestoryTimeLine.go,1C42F2CB5EA373A2CE6DC76AEBAEFA59,1341,1682318037761
|
||||
c:/tmp/go/Game.LinestoryTimeLineData.go,F39DEB17F5F8D4C5B2ACD0AA975249D,3326,1682318037624
|
||||
c:/tmp/go/Game.Lottery.go,433ADD2BECD6C41A17A419A32289755,1188,1681198061135
|
||||
c:/tmp/go/Game.LotteryData.go,E9495B4FE19922F8F921DD16A4E55D8,4296,1681198061214
|
||||
c:/tmp/go/Game.Mail.go,2CCB7CF093BE78F516DCDFEC05EA0,1147,1675761410231
|
||||
c:/tmp/go/Game.MailData.go,E274CF9D08A6EEB3D3FE4863E637A3,3629,1678261258950
|
||||
c:/tmp/go/Game.MainChapter.go,7E1BF84D63C3316377CF93468CBDE7,1248,1675761410218
|
||||
c:/tmp/go/Game.MainChapterData.go,CE9127C4D8CFB5F8AE59B33B9447FCDC,3038,1675761410193
|
||||
c:/tmp/go/Game.MainStage.go,431DA6BC2D5F8B51B68EF9D9257B77,1218,1675761410254
|
||||
c:/tmp/go/Game.MainStageData.go,6491A7EA8892FC144209A4E8F69CD26,11127,1681972759520
|
||||
c:/tmp/go/Game.MainStarreward.go,88819424B3CBEB1F5697B90CAC155F2,1293,1675761410230
|
||||
c:/tmp/go/Game.MainStarrewardData.go,82C859415EA7A23AC6425C3B8746A0F3,2169,1675761410265
|
||||
c:/tmp/go/Game.MainStartype.go,C803E13932B2A686D4957A0F93B5B4B,1263,1675761410218
|
||||
c:/tmp/go/Game.MainStartypeData.go,C3FDCE5FE973BD54CB70F16A72A7C8,1513,1675761410243
|
||||
c:/tmp/go/Game.Model.go,4999368ACDD4EA1AA7A7B0F45D3F30,1162,1675761410214
|
||||
c:/tmp/go/Game.ModelData.go,7284A2299C35387A68EC47255DDB14,5880,1682218335290
|
||||
c:/tmp/go/Game.ModelStateType.go,C18E5EB988FEC4C136C8EE58CC4D4C87,475,1675761410265
|
||||
c:/tmp/go/Game.Monster.go,DCC8EED950F78592F3EAB351401EA4B,1195,1675761410250
|
||||
c:/tmp/go/Game.MonsterData.go,78AD18C6F69AF9B49AA3B15E81DC0C1,2953,1675761410202
|
||||
c:/tmp/go/Game.MonsterFormat.go,6BC29CD8E3D5A270964E5616ADF1B6BC,1033,1675761410259
|
||||
c:/tmp/go/Game.MonsterFormatData.go,F76DFC4DC971105098BBDB82B194BDA,3008,1680601670124
|
||||
c:/tmp/go/Game.Msgdistrib.go,7D776BA16AD6E9FEE1A14DFD47282CCD,1240,1675761410273
|
||||
c:/tmp/go/Game.MsgdistribData.go,2A17D832F91DA826297AB0269A401455,1434,1675761410201
|
||||
c:/tmp/go/Game.NameLibrary.go,79B0B576224A96DFB0C3AF98B984317,1248,1675761410197
|
||||
c:/tmp/go/Game.NameLibraryData.go,90732082E97654A7488AF3BD49B42BAD,1928,1675761410236
|
||||
c:/tmp/go/Game.Navigation.go,3C5AD8314849EDB2BF9A857DEF7B7C,1233,1681972759483
|
||||
c:/tmp/go/Game.NavigationData.go,B1F69D982280B87BA98F946D5FEA8D96,2553,1681972759483
|
||||
c:/tmp/go/Game.NewRedDot.go,5852E83FC4CA63D87D8172ADB45D2F,1218,1681962385982
|
||||
c:/tmp/go/Game.NewRedDotData.go,1D47B6AFD13E53D958C738FE27C4EB0,2250,1681962385979
|
||||
c:/tmp/go/Game.NewSmithy.go,D469AF878FFF8381B3863F6EDFAA4F1,1218,1676518692457
|
||||
c:/tmp/go/Game.NewSmithyData.go,19B7778B8E753B5521EDF118ED2205A,5910,1679909505407
|
||||
c:/tmp/go/Game.Opencond.go,1F68A5B032F3CFF2B0131A38546AEE1,1207,1675761410239
|
||||
c:/tmp/go/Game.OpencondData.go,97E5882198742EA74274EA630346AD6,4198,1680601670124
|
||||
c:/tmp/go/Game.OpencondType.go,96DBF7463A0C961739BB9B844FD89C6,511,1675761410276
|
||||
c:/tmp/go/Game.OpenedCond.go,D9244B4D44EF4E41EB8A70D78B1B9F97,1218,1675761410226
|
||||
c:/tmp/go/Game.Pagoda.go,4D356552318B111BE2B4CFB1961D88F0,1174,1679542643325
|
||||
c:/tmp/go/Game.PagodaData.go,77B2A12C94294CB9B27054EDE4F94C80,5185,1679542643190
|
||||
c:/tmp/go/Game.PagodaTaskReward.go,A185223EB8F3EB73654242898BE60,1324,1675761410238
|
||||
c:/tmp/go/Game.PagodaTaskRewardData.go,73E72E27BCA9AC178B13F9FA7B3E98E6,2219,1675761410225
|
||||
c:/tmp/go/Game.PandamasBuff.go,26D88E88F317A7FAEA8A7846FB24C7B,1263,1677226965190
|
||||
c:/tmp/go/Game.PandamasBuffData.go,A152AF66A560C251365124DAE64C58A,2909,1677226965193
|
||||
c:/tmp/go/Game.PandamasJs.go,74F3CB7776FB319BE511FBAFDF63DC87,1233,1677226965191
|
||||
c:/tmp/go/Game.PandamasJsData.go,F49416080E83A4D59E79D3BB125D95,1771,1679542643180
|
||||
c:/tmp/go/Game.PandamasJx.go,D0847C6324EA5F28FEA4AABA9F8B90,1237,1677226965186
|
||||
c:/tmp/go/Game.PandamasJxData.go,97B23A18FDABC658DE5AE99691A3089,7041,1681962385979
|
||||
c:/tmp/go/Game.PandamasMryl.go,3F8E41E3B96819112E47CC7E92F1,1263,1677226965188
|
||||
c:/tmp/go/Game.PandamasMrylData.go,AC877F9235CC8C85304997F2492F55DD,3190,1681962385984
|
||||
c:/tmp/go/Game.PandamasMz.go,B354BCB3152A3982225874F09F41BA,1233,1677226965187
|
||||
c:/tmp/go/Game.PandamasMzData.go,6255D83E89A4BFDCE0FFD9AE21BEC8D,4272,1677226965188
|
||||
c:/tmp/go/Game.PandamasTj.go,C671C04FBF5B8FCB2207DC26057A938,1237,1677226965186
|
||||
c:/tmp/go/Game.PandamasTjData.go,813474EA84B63AADF954E41222F960,2872,1680494109544
|
||||
c:/tmp/go/Game.PandamasTjjl.go,456BB15F9994578B41DB7632C432E386,1268,1677226965187
|
||||
c:/tmp/go/Game.PandamasTjjlData.go,E452B6D769B82E133EE2129306AAA99,2008,1677226965188
|
||||
c:/tmp/go/Game.PandamasYxjx.go,68DAFE10A4119A9CC547EFE6F39635D,1263,1677661885207
|
||||
c:/tmp/go/Game.PandamasYxjxData.go,2CEB308E69B1BEF43792574D3B21941,2305,1677661885224
|
||||
c:/tmp/go/Game.PassCheck.go,80982CAF6A7F345EA4BF3CA4103DF0,1218,1675761410193
|
||||
c:/tmp/go/Game.PassCheckData.go,DEC969FF4DCF889490DBDE84E3A02E5F,2593,1675761410209
|
||||
c:/tmp/go/Game.PayPackage.go,3E57B994B1D847B2F9AFC93AC390B,1233,1675761410267
|
||||
c:/tmp/go/Game.PayPackageData.go,30533C4BEDBABA987DC0133C3D1E5F5A,3933,1675761410244
|
||||
c:/tmp/go/Game.PlayerInfor.go,596C8A9D4AE64BAB26D15BF8DB5FC94B,1248,1675761410269
|
||||
c:/tmp/go/Game.PlayerInforData.go,E4B4ADB854FD69DDBC4E5E59564DB60,1649,1675761410246
|
||||
c:/tmp/go/Game.Playerlv.go,593E2F4848329C83D1E1A5B3A14D9A7,1203,1675761410239
|
||||
c:/tmp/go/Game.PlayerlvData.go,618EF84561B44786F0EB1F52DDE14B,2352,1675761410226
|
||||
c:/tmp/go/Game.PotionFly.go,16DB7E99F4981DB3558C664136259E,1542,1681126805544
|
||||
c:/tmp/go/Game.Potions.go,67BA8089876BE652144AFC2E92279234,1188,1680056393181
|
||||
c:/tmp/go/Game.PotionsData.go,825CBCF3B8772455A3D764E9E3D0A4,7660,1680494109582
|
||||
c:/tmp/go/Game.Privilege.go,A7942237F4DCEBDB92DB7D68C439770,1227,1675761410231
|
||||
c:/tmp/go/Game.PrivilegeCard.go,3DBC6B483893844BB13E8D5A7BF1D,1282,1675761410244
|
||||
c:/tmp/go/Game.PrivilegeCardData.go,2EF0885473BB89E511DEAD8CA7D78D1B,3899,1675761410255
|
||||
c:/tmp/go/Game.PrivilegeData.go,25541DCCA4997445E28198D08E5FD83,2548,1675761410196
|
||||
c:/tmp/go/Game.PropertyType.go,A520805A56672C27373103F71290FB,3107,1675761410217
|
||||
c:/tmp/go/Game.RdtaskCondi.go,A9C52348E4B3E048D862FAA6F3E99AE2,1248,1675761410200
|
||||
c:/tmp/go/Game.RdtaskCondiData.go,704B4AB7647CFB647AF34FF3BAD731CB,3179,1680494109544
|
||||
c:/tmp/go/Game.RdtaskNpc.go,8303FEA3729A34A6C42A8A0D9DBCA7E,1218,1679651030018
|
||||
c:/tmp/go/Game.RdtaskNpcData.go,D76447578211DB94233971EF7D10B354,2613,1681962385979
|
||||
c:/tmp/go/Game.Recharge.go,CD9CEA129FD2B7E8A182D2AE292D2EB9,1207,1675761410268
|
||||
c:/tmp/go/Game.RechargeData.go,96E682AA6A58EB1282D8DD29C32511,3594,1675761410206
|
||||
c:/tmp/go/Game.RedDot.go,4258EE22DEAA981D18A4EE22DE5BF9B,1173,1675761410193
|
||||
c:/tmp/go/Game.RedDotData.go,579A366069A8549B59FB1F1F25B8A1E,2136,1675761410267
|
||||
c:/tmp/go/Game.RedDotGroup.go,F838A6313C46125BEE82A673AD8275F8,1248,1675761410255
|
||||
c:/tmp/go/Game.RedDotGroupData.go,CC59A060E2DF66558DEEC57CDE30E6,1651,1675761410244
|
||||
c:/tmp/go/Game.RedDotTalkid.go,34F41711EB70CBCFB514D431EA86A55,1267,1675761410231
|
||||
c:/tmp/go/Game.RedDotTalkidData.go,AA3CFE3FA79EF06FC49F6CB6EC40C25A,1513,1675761410219
|
||||
c:/tmp/go/Game.Robot.go,D09D3DE1A46A9C6E6552A2E443249FE,1163,1675761410270
|
||||
c:/tmp/go/Game.RobotData.go,B4D515ABDA2F2C2628E89DF4A4E0B6F0,7379,1675761410223
|
||||
c:/tmp/go/Game.SellCoefficient.go,F073B3D7FD151232BDF7D87627DE521,1315,1680179912087
|
||||
c:/tmp/go/Game.SellCoefficientData.go,D2E71712AA58BEDD89D36FDA5E452DB,1323,1680179912040
|
||||
c:/tmp/go/Game.Shop.go,CF679DDEC3647AFA6BDCE3713CCD99B2,1147,1675761410213
|
||||
c:/tmp/go/Game.ShopData.go,C0C88D365AD827F32EEC193BED1225,4719,1675761410274
|
||||
c:/tmp/go/Game.Shopitem.go,B7D6921622189F85578E787CC73B1B82,1204,1675761410227
|
||||
c:/tmp/go/Game.ShopitemData.go,7CB82627F9737ED8936E7A6840AD8A32,5158,1675761410262
|
||||
c:/tmp/go/Game.Show.go,5D15E4F9362328FFFC5B21139CED5CE,1143,1675761410234
|
||||
c:/tmp/go/Game.ShowData.go,B643E79E4E72EDB8E84554C661842EA5,2241,1675761410269
|
||||
c:/tmp/go/Game.Sign.go,23FEDD52B1DA9D60C3B1D6DE3455F3D,934,1680248624386
|
||||
c:/tmp/go/Game.SignData.go,7FFB1D358C63DC8354D88F34724575,2819,1680234417438
|
||||
c:/tmp/go/Game.SignExtra.go,AAE12E1DCE621959278EF43AA978557,989,1680248624370
|
||||
c:/tmp/go/Game.SignExtraData.go,9E3C8EB18CCBF2B9D5B497CBFF2380A7,2544,1680576438283
|
||||
c:/tmp/go/Game.SignReset.go,BBC3B1BE73A4F2C02CDEBC1AC59EDACF,1218,1675761410221
|
||||
c:/tmp/go/Game.SignResetData.go,E9772BD6B78F3EAB1199134CEAA9E60,1237,1675761410206
|
||||
c:/tmp/go/Game.SkillAfteratk.go,8F66AF7A9C42132CB3C5FA2AB5F26,1278,1675761410264
|
||||
c:/tmp/go/Game.SkillAfteratkData.go,B8CFFB8B098C3CA5EA45B443527B684,6651,1675761410242
|
||||
c:/tmp/go/Game.SkillAtk.go,6B7A4B2BAE054AAA7FAE193E30498D,978,1675761410217
|
||||
c:/tmp/go/Game.SkillAtkData.go,D5A2ECF1D186BF242E70EA48F63F3781,5220,1675761410204
|
||||
c:/tmp/go/Game.SkillBuff.go,C477B24C65A9E283C9BA79591E1E9,1218,1675761410229
|
||||
c:/tmp/go/Game.SkillBuffData.go,56E6A61D9DD9CC79D4A7FD5A249CEE1,5753,1681962385984
|
||||
c:/tmp/go/Game.SkillEffectType.go,2A51476E33DC9A780DE21F2D5807D88,1827,1681962385979
|
||||
c:/tmp/go/Game.SkillPassive.go,9B287E1A5BCDCAED93EEE9EA71B58CD,1263,1675761410253
|
||||
c:/tmp/go/Game.SkillPassiveData.go,44EC745353A7734F7808DCFB455E31,3799,1675761410264
|
||||
c:/tmp/go/Game.SmithyAtlas.go,5B5AABF2AA7BF212FD8CA97C766D7C4F,1252,1677038179629
|
||||
c:/tmp/go/Game.SmithyAtlasData.go,BFC954D5A8835912E92D976CA6DE51,3158,1677059652972
|
||||
c:/tmp/go/Game.SmithyAtlasLv.go,F86EA4795B59D25AB79703766A272D,1283,1677038179630
|
||||
c:/tmp/go/Game.SmithyAtlasLvData.go,E85FA0129FDCC348EAE6785CC48DE2A2,2015,1677038179619
|
||||
c:/tmp/go/Game.SmithyAtlasScore.go,12E094F46395632E8A6B5EF9C889ACC6,1323,1677038179615
|
||||
c:/tmp/go/Game.SmithyAtlasScoreData.go,18BCB139BEB6192E3F17B4A5B78D7D2,1652,1677038179617
|
||||
c:/tmp/go/Game.SmithyCustomer.go,55F61C14D9D7B551E449EC4390BC341E,1301,1676518692454
|
||||
c:/tmp/go/Game.SmithyCustomerData.go,2EC2224D34934FB052C6837D666AF29B,3400,1676526348334
|
||||
c:/tmp/go/Game.SmithyIdTool.go,5B551B697E9DCD4DE9BAE46317E77454,1263,1677226965191
|
||||
c:/tmp/go/Game.SmithyIdToolData.go,B9C35177B62E1EEADF33C3D2451EFB3,3671,1678073991276
|
||||
c:/tmp/go/Game.SmithyMake.go,C011169752EBE4B81BA5C8C0168F501F,1239,1679906281543
|
||||
c:/tmp/go/Game.SmithyMakeData.go,4321F6CF81B013DC4CF08C48B76F12EA,1739,1679906281542
|
||||
c:/tmp/go/Game.SmithyModelPool.go,CD4B1CBFE957EB8945C60B05E498BE0,1308,1677226965375
|
||||
c:/tmp/go/Game.SmithyModelPoolData.go,6C86F150B054D0C81834F6BD757B383E,1496,1677226965192
|
||||
c:/tmp/go/Game.SmithyProficiency.go,3F4E21F7E5A8FBAC83B1F16969569A7,1077,1677038179619
|
||||
c:/tmp/go/Game.SmithyProficiencyData.go,C57C14E515189738F730CF85DFF0585E,3202,1677038179628
|
||||
c:/tmp/go/Game.SmithyStoveV1.go,EDC5BCC4F9716514F3ACC7E444EC2C5,1280,1676518692454
|
||||
c:/tmp/go/Game.SmithyStoveV1Data.go,9DE078FD641B767826D5D4D8769DD4,2739,1676518692454
|
||||
c:/tmp/go/Game.SmithyTask.go,AEA846A9A27F5648A3A68B90D365D9E2,1234,1677038179623
|
||||
c:/tmp/go/Game.SmithyTaskData.go,6FB0F235B355C28D1F818999A3E214C,2612,1677038179621
|
||||
c:/tmp/go/Game.SmithyTool.go,BA1AB18ADBEC3ADF684EB9367BC54410,1000,1677038179623
|
||||
c:/tmp/go/Game.SmithyToolData.go,91A1870553BA719F55B148B9732AB,3659,1678073991288
|
||||
c:/tmp/go/Game.Talent.go,71C5E99251DF6A3E145E925FD21D6398,1173,1681962385984
|
||||
c:/tmp/go/Game.TalentData.go,DA1E97255EFCA9E3090E748BE89C62E,4727,1681962385981
|
||||
c:/tmp/go/Game.TalentSkill.go,F9BF1EF61E90EFA4C9DD1FC9ED975491,1253,1675761410235
|
||||
c:/tmp/go/Game.TalentSkillData.go,4C4BB723ED2FC6F382A6C7737146C80,3226,1675761410222
|
||||
c:/tmp/go/Game.TaskActiveReward.go,97E47A5C9F7CB0E61CB7CD9A37BE72D1,1324,1675761410250
|
||||
c:/tmp/go/Game.TaskActiveRewardData.go,7A3E6C5FBAF21AA96B9FBE9757C618,2512,1682218335278
|
||||
c:/tmp/go/Game.TaskRound.go,D020EA2F956FF3BDB642ED35F282E45,1219,1675761410226
|
||||
c:/tmp/go/Game.TaskRoundData.go,CEB761591786919F1CA8AB01901D,3531,1675761410273
|
||||
c:/tmp/go/Game.Teaching.go,7F2ECF64117D5123826E88EDEC61F689,1203,1675761410268
|
||||
c:/tmp/go/Game.TeachingData.go,EFBBFBCC922ED6C1B37A86CEA5C94F25,6715,1680513216868
|
||||
c:/tmp/go/Game.TrollCoefficient.go,5380DB70872B18DB63C738CE5924644E,1323,1675761410268
|
||||
c:/tmp/go/Game.TrollCoefficientData.go,99F5FA24C3E1DC5089F6671D9113E1D9,1306,1675761410207
|
||||
c:/tmp/go/Game.TrollGoods.go,145AB09F76C13B7DABCFA9E9C329FBD7,1233,1675761410207
|
||||
c:/tmp/go/Game.TrollGoodsData.go,EB8C912D59BD09BDD43A12E209EA62,3777,1676518692455
|
||||
c:/tmp/go/Game.TrollLv.go,7FA827993355F49AD852BA798351EFC,1188,1675761410232
|
||||
c:/tmp/go/Game.TrollLvData.go,3F116F498DBDB84A3BBB417BE045C5,2499,1675761410221
|
||||
c:/tmp/go/Game.TrollRule.go,512BD4EDA3F94C1A3CD2FE715CF5D17,1218,1675761410233
|
||||
c:/tmp/go/Game.TrollRuleData.go,059E5EC96C4953FFCD1864CEB8C7C,1243,1675761410268
|
||||
c:/tmp/go/Game.TrollTrain.go,C2D8F9A1FBDB2687545A7BCCE1CB91A,1233,1675761410256
|
||||
c:/tmp/go/Game.TrollTrainData.go,2572D0CF6615D369BCED75549AC6971,1648,1675761410196
|
||||
c:/tmp/go/Game.VikingBoss.go,E7AB8CB8AA2B84546C5123AC0A1FE56,1000,1675761410225
|
||||
c:/tmp/go/Game.VikingBossData.go,EF135139EE5F6F6F7FB3B5FC1EF1706E,7198,1675761410237
|
||||
c:/tmp/go/Game.VikingBossSkill.go,951D4526F1116AF36D673D1BEB482CA9,1312,1675761410237
|
||||
c:/tmp/go/Game.VikingBossSkillData.go,374832A711689D3D3C2CC58FDE5968,2964,1675761410259
|
||||
c:/tmp/go/Game.VikingChallenge.go,BC5F1D76EEE9C6B17ADFCD3DBD7CE91,1312,1675761410199
|
||||
c:/tmp/go/Game.VikingChallengeData.go,CB693365C1D132E8141F14A8B832F8CB,1800,1675761410260
|
||||
c:/tmp/go/Game.VikingEntrance.go,328C6C2D94321A7D7991385F4B69EA,1297,1675761410272
|
||||
c:/tmp/go/Game.VikingEntranceData.go,B237211BA19D1377959288D2A3EA8BA3,2671,1675761410248
|
||||
c:/tmp/go/Game.VikingLineup.go,2D98B23891EDCF72C92196D869DAD8FC,1263,1675761410211
|
||||
c:/tmp/go/Game.VikingLineupData.go,F3CF9119717CFF771457DE441F244B,1654,1675761410224
|
||||
c:/tmp/go/Game.Vip.go,102F7FD577B9CE145EB64136276FDB,1131,1675761410230
|
||||
c:/tmp/go/Game.VipData.go,211F15FBA462EDBF8D9D15982FA47C0,4643,1675761410255
|
||||
c:/tmp/go/Game.WorldAll.go,9AF391CD98756EB4C74834447E31A,1203,1680055388974
|
||||
c:/tmp/go/Game.WorldAllData.go,2E35E4903FCFB4E5FEC7F3AC1825BEF,2768,1680055389013
|
||||
c:/tmp/go/Game.WorldBattle.go,9CE09F1EF199BFF5A6AF63235780703C,1248,1675761410255
|
||||
c:/tmp/go/Game.WorldBattleData.go,2E1F5F0FB60E811E14C9AAB5A68AE27,2825,1675761410205
|
||||
c:/tmp/go/Game.WorldTask.go,434D20C017E6DFFBCCA08EBC4754594,1219,1675761410219
|
||||
c:/tmp/go/Game.WorldTaskData.go,A5F9A7F71EB52893B5A4CFADA99FB7,7131,1681962385978
|
||||
c:/tmp/go/Tables.go,B971E075C0D6E797733C169D1733BA,42164,1682218335290
|
||||
c:/tmp/json/game_activereward.json,D3EED68F53E4C4B4365DE3B2157AC33E,841,1682307537195
|
||||
c:/tmp/json/game_arenaactivereward.json,BF1CCCAC8E9C4484952427885249F8B9,3332,1675761410715
|
||||
c:/tmp/json/game_arenabuychallenge.json,99244E8D8265F317C1791A8096BCF7B8,1308,1675761410715
|
||||
c:/tmp/json/game_arenachallengenpc.json,DAE11F4AB0754268A2FAEF5936B54AA,8391,1679296385065
|
||||
c:/tmp/json/game_arenarankreward.json,43CB1836B7DB877BDE9436FAB2578C53,2883,1675761410716
|
||||
c:/tmp/json/game_arenarobot.json,32FBEC8F41611E6C8C852174FB7DB1,1530,1675761410715
|
||||
c:/tmp/json/game_battleready_capskill.json,EA775AAAFEDB8471A3C94E89938983,219,1677038179630
|
||||
c:/tmp/json/game_battleready.json,587110213BB78332A821AAED1D63DD81,7666,1681962386033
|
||||
c:/tmp/json/game_battletasktesting.json,5F772617E8A89921C3CFFB1EF3943E60,81,1675761410764
|
||||
c:/tmp/json/game_breakingbad.json,FFC05F7A6F323B74A81A42F5DAD1E2,2740,1681962386032
|
||||
c:/tmp/json/game_breakingbadtag.json,19871E5F86D8C3B9DF41F2AE78F39099,217,1680144063147
|
||||
c:/tmp/json/game_bubblegroup.json,85696680D892AC8BC4A0AF1F72745F44,6674,1681962386040
|
||||
c:/tmp/json/game_buzkashifm.json,EC7F2F581EE6BA14CC7A64E43E122B5,1919,1682218335507
|
||||
c:/tmp/json/game_buzkashigrade.json,D47715ABEC98A3D08355929C759D76C9,259,1682218335505
|
||||
c:/tmp/json/game_buzkashilv.json,3A904DE2A9123159792B15369C342C,380,1682057107480
|
||||
c:/tmp/json/game_buzkashimount.json,5888FC4FD7D9C78CCABDC97CE1F5BDB4,1155,1682318037909
|
||||
c:/tmp/json/game_buzkashiopen.json,BEB2D3F76A1A55A63094FA4E75EAF4C5,2422,1682218335506
|
||||
c:/tmp/json/game_buzkashireward.json,9DF6F6EDED492A97DADB9ECBBE0229,931,1682057107479
|
||||
c:/tmp/json/game_camplv.json,EA5BD2C3B5146949F5F08E51E476A610,14406,1682057107479
|
||||
c:/tmp/json/game_chatchannel.json,1F87E9D83A3FC71A26AB2A8F14A0DA,428,1675761410386
|
||||
c:/tmp/json/game_chatchannelcom.json,58D258F42C2A1911CE87A5BE80BB4A,695,1675761410386
|
||||
c:/tmp/json/game_chatexpression.json,B432A821EFFBED64D729B541AA3F8A1,1527,1675761410385
|
||||
c:/tmp/json/game_chatservergroup.json,23D3A6BD53D0AC8AE14B408EEB8A94D1,954,1675761410386
|
||||
c:/tmp/json/game_chatsystem.json,80EBFB9522C4DBB05EE29ED2A5F34476,8010,1675761410386
|
||||
c:/tmp/json/game_coin.json,A9A9AE5A4EC5474B8B4247F5D7B93D1,4720,1681972759519
|
||||
c:/tmp/json/game_combatbox.json,8A3AB7F11E9B9C769A54AA8638BB99,1084,1678677256017
|
||||
c:/tmp/json/game_combatlevel.json,D7406EB1BA1329D9992A34DBBD72EE1,4920,1678677256017
|
||||
c:/tmp/json/game_combatmanster.json,6E581C2DA6262A536F085E3916AEEE7,5851,1675761410751
|
||||
c:/tmp/json/game_dispatch_battle.json,8B44C83A9F7A4E662EB4C20797B47AF,1591,1681962386032
|
||||
c:/tmp/json/game_dispatch_lv.json,34A2726CDC3BF7DCFCE3B7D6C773767,579,1680144063145
|
||||
c:/tmp/json/game_dispatch_task.json,36A8854A8812B5F96E0115E8577AD,61669,1682218335498
|
||||
c:/tmp/json/game_drawcard.json,66D94B48C4B37CACBE7740F771CA7A,19860,1681962386238
|
||||
c:/tmp/json/game_dreamlandboos.json,1888542E62918AE029C779C6FB6B4F44,1036,1675761410629
|
||||
c:/tmp/json/game_dreamlandchallenge.json,4335C14D448FA128DB60BB96197CBC1D,1335,1675761410611
|
||||
c:/tmp/json/game_dreamlandtrigger.json,28F884577B6D1A1956E322C6CC78B742,358,1675761410629
|
||||
c:/tmp/json/game_drop.json,7527B859F8AD5C1E666CF38E41EEA9,49284,1677661885209
|
||||
c:/tmp/json/game_enchantboss.json,15B0447F42A1ACA9918F5FD26F9FB9,38976,1675761410758
|
||||
c:/tmp/json/game_enchantlineup.json,EF9670D72E9BBAA16B1D8C1807A3D1C,3132,1675761410759
|
||||
c:/tmp/json/game_enchantshop.json,4335C14D448FA128DB60BB96197CBC1D,1335,1675761410755
|
||||
c:/tmp/json/game_equip.json,8EBBC6B2589ADEC7CAF501A9BE6229,540254,1680333520554
|
||||
c:/tmp/json/game_equipattribute.json,41E55A8C70C1D823E477A72A3C5CF12,17487,1675761410677
|
||||
c:/tmp/json/game_equipattrlibrary.json,7AA7643ADD129C81BB8CD7D6688D349,147142,1680333520466
|
||||
c:/tmp/json/game_equipcolor.json,23E75AC519FB233B146AAD1F873817DF,513,1675761410679
|
||||
c:/tmp/json/game_equipenchanting.json,E498711A7E962CA6F19BB3F3F5224F,4302,1675761410625
|
||||
c:/tmp/json/game_equipintensify.json,5F667FFE282E3429CF353FCC58246A15,79062,1675761410488
|
||||
c:/tmp/json/game_equippos.json,AF6858A6A6DFDBF3254186A81BFD7E8,2029,1680333520453
|
||||
c:/tmp/json/game_equipscompose.json,EC69D955CBCE89EB317A461952521385,25080,1675761410679
|
||||
c:/tmp/json/game_equipsuit.json,67A562B61E407C9B64CF9447DE1BCCA,7435,1680333520554
|
||||
c:/tmp/json/game_extservers.json,3646EC79C54DD7CAAC569C7F963BB0,1068,1676518692477
|
||||
c:/tmp/json/game_facemod.json,2BBA2B6F9A82AB2EC8844559D3BB961,6593,1675761410656
|
||||
c:/tmp/json/game_favorability.json,4E3EFA49AA4D8D14760B0F2F7ED3639,67752,1682218335505
|
||||
c:/tmp/json/game_fightglobalevent.json,E837C59BA038C4215526E661918BACC,12340,1675761410750
|
||||
c:/tmp/json/game_friends.json,BDF1452119B56592733A6357F28E9BC,8725,1682218335499
|
||||
c:/tmp/json/game_getresource.json,C46E1E2C5D426C4ECA4A894552BE9444,653,1675761410348
|
||||
c:/tmp/json/game_global.json,1066827E2E81DEB540959BEE511E196E,14307,1682307537246
|
||||
c:/tmp/json/game_gm.json,FB48EFD74530879D2A296651ACB1AB32,5966,1681962386232
|
||||
c:/tmp/json/game_gourmet.json,CC74365D5C8D55A4D7872321E5FB6065,55949,1675761410364
|
||||
c:/tmp/json/game_growreward.json,4A588FDE3912B77387372D9EDB6562,965,1675761410741
|
||||
c:/tmp/json/game_growtask.json,AF7BAC9838F83F887A4CE3F4092F4E6,8061,1675761410741
|
||||
c:/tmp/json/game_guide.json,D751713988987E933198363E24189CE,2,1680164540236
|
||||
c:/tmp/json/game_guildactivity.json,FBC9A5965931DFB7BEB5CF3D98AC514,774,1675761410718
|
||||
c:/tmp/json/game_guildbosstask.json,49AC51648FDDA5E7A04154456B693F71,2585,1675761410719
|
||||
c:/tmp/json/game_guildlv.json,854216455BDAF1C4B35A728B9AA2A,1321,1675761410718
|
||||
c:/tmp/json/game_guildpng.json,34F523EBCD9D3702C9A968D961720BB,588,1675761410718
|
||||
c:/tmp/json/game_guildsign.json,5AC221945DD8EBF17E4D396E8673AED1,2100,1675761410718
|
||||
c:/tmp/json/game_guildtask.json,C2CF857203DAEB0F7202853A21363F6,4875,1675761410718
|
||||
c:/tmp/json/game_help.json,EA598AF8FDAC88C32EFF99A04881E,460,1675761410752
|
||||
c:/tmp/json/game_hero.json,D3709DAFE361BDA74EC1AAA3CFD78D,159832,1681962386232
|
||||
c:/tmp/json/game_heroawaken.json,71519DD7974DA3B322F4781EC3DBB37F,476483,1675761410481
|
||||
c:/tmp/json/game_heroconvertdata.json,9A577728E5D9D9B68EABF977F9241CB,187,1675761410333
|
||||
c:/tmp/json/game_heroexp.json,EE1C209B4B92591F664BBDE369B2F45D,235,1680144063077
|
||||
c:/tmp/json/game_herofusion.json,F93DD49FB7D6DD11699E91AC9BFD4,1488,1675761410331
|
||||
c:/tmp/json/game_herolevelgrow.json,D5E55EB88D3D3EEDA9ED79174B784C3,27074,1675761410714
|
||||
c:/tmp/json/game_herolevelup.json,866D2340E76750343B7E18F33271BD,6148,1675761410624
|
||||
c:/tmp/json/game_heromethod.json,1D6FA854ECD8ECA89452D227F29A8C,22084,1675761410441
|
||||
c:/tmp/json/game_heromethodcomment.json,306BB7AFCD3082E32392A6CEC3874D53,1281,1675761410440
|
||||
c:/tmp/json/game_heroskill.json,4A88CE65A0BF37E0ADD37CD840438252,813,1675913368405
|
||||
c:/tmp/json/game_heroskilllevel.json,1B35D2B4791992C3C948D037A438B1EC,30888,1675761410624
|
||||
c:/tmp/json/game_herostargrow.json,A79CA6CC1FDB28663861644CEF16091,950,1675761410714
|
||||
c:/tmp/json/game_herostarup.json,F177296407A285B47DD5EA0BC2CD384,68269,1678677255844
|
||||
c:/tmp/json/game_herostrategy.json,6745F13142D4532DE6F7BF8DB73BF7,15046,1680513216867
|
||||
c:/tmp/json/game_herotalent.json,329FDEDC9B9F228ECF3412C4619A6E,7092,1675761410331
|
||||
c:/tmp/json/game_horoscope.json,81D7D6BAC274963F6D4315F0CBA9ED3D,238307,1675761410739
|
||||
c:/tmp/json/game_huntingboss.json,DC33AE6BD9CEA106F3DB2DBFC3C40B8,32411,1682218335416
|
||||
c:/tmp/json/game_huntingchallenge.json,4335C14D448FA128DB60BB96197CBC1D,1335,1675761410611
|
||||
c:/tmp/json/game_huntinglineup.json,6356433D4FCB4ECE85D25E797D74B5C3,3567,1675761410348
|
||||
c:/tmp/json/game_huntingopentime.json,132066502E243CFA89E0447788188E1,1821,1675761410611
|
||||
c:/tmp/json/game_initial.json,498FD44D5B84BB2CEC8CD5853740E56F,21232,1682057107478
|
||||
c:/tmp/json/game_item.json,DE86B3FEF01617FB98CBFF5F7F321CC,164623,1682307537217
|
||||
c:/tmp/json/game_itembox.json,F8D458C8CC5E3EB58B35D11E6259EF6E,4192,1675761410717
|
||||
c:/tmp/json/game_itinerant_city.json,76D06B4496E4FD8E0D7B85237141A5,3332,1681962386029
|
||||
c:/tmp/json/game_itinerant_lv.json,A42A4E26426C85A00EDEDA4C2B53F,1974,1681962386030
|
||||
c:/tmp/json/game_itinerant_reward.json,467883995F3C3CF65ABC5E6D6D12FA8,408,1681962386038
|
||||
c:/tmp/json/game_itinerant_thing.json,B1F162027D1C14CA736F1EFBF310E8,3849,1681962386039
|
||||
c:/tmp/json/game_librarybubble.json,8154AF3EED738D65113A8E356B11697A,384,1675761410337
|
||||
c:/tmp/json/game_librarycomplot.json,5B941EF48E4C3D457D926BFA5B2B686,3792,1675761410337
|
||||
c:/tmp/json/game_libraryfavor.json,EB684CA2609C631516D18BA121C4A97,1662,1675761410337
|
||||
c:/tmp/json/game_libraryfavorlv.json,8DEEBD3AF3166ED6E5C5837DC2F94BB8,441,1675761410337
|
||||
c:/tmp/json/game_libraryfetter.json,BAF8A2E4B7887BBD46C485D8AC674,3221,1675761410347
|
||||
c:/tmp/json/game_libraryhero.json,D3C53DB0D9EA31DBF512FEC9871F618,19393,1675761410347
|
||||
c:/tmp/json/game_libraryhistory.json,70AAA0D3E0E032D1443AD8E8A5D4DC7,92338,1675761410345
|
||||
c:/tmp/json/game_libraryplayback.json,94C2236AE30C59D353190301725B6,1159,1675761410337
|
||||
c:/tmp/json/game_librarystory.json,80B39EF0EBA748851BFD25E320A7B0,477,1675761410347
|
||||
c:/tmp/json/game_linestorymaintask.json,39D1B19C8B1D2E4773AF38FF2C9FEC12,3329,1682318037448
|
||||
c:/tmp/json/game_linestorytimeline.json,C66A644E3F77E141A9DFCF4745536EAC,3264,1682318037453
|
||||
c:/tmp/json/game_lottery.json,75BB73436CA0187AE923BB379C480A9,13722,1681962386039
|
||||
c:/tmp/json/game_mail.json,696DC699EB6CE88CEED681E42F90759B,5946,1678271315132
|
||||
c:/tmp/json/game_mainchapter.json,F4352CC5AFD2764A0B390D1F9F41B,14884,1678271315126
|
||||
c:/tmp/json/game_mainstage.json,EFA1D92EDC3B10979A734C1642BDFE0,37978,1681972759518
|
||||
c:/tmp/json/game_mainstarreward.json,4625A9BDCA1B4D3A1BE3A3394D1ED38,2070,1675761410764
|
||||
c:/tmp/json/game_mainstartype.json,DFA5E7D4B19CDC5D642A8044361A8B,372,1675761410764
|
||||
c:/tmp/json/game_model.json,A64F6A18C7E08F4134CC8A1050D53FA9,76525,1682218335477
|
||||
c:/tmp/json/game_monster.json,FCCB6CF9743257A813B841D742C36C0,187449,1678677255914
|
||||
c:/tmp/json/game_monsterformat.json,2C5EE5F6D01147AC2BA535FB1A1471D,1517045,1682218335416
|
||||
c:/tmp/json/game_msgdistrib.json,16C3102AC7C04E448CFAB7C44D8FAC1,2604,1681972759486
|
||||
c:/tmp/json/game_namelibrary.json,40EE974E25A19B35376F1F91DC1B2545,23511,1675761410334
|
||||
c:/tmp/json/game_navigation.json,17C79B5C488D03F4448B3672FBE9C6,8233,1681972759519
|
||||
c:/tmp/json/game_newreddot.json,8E38D0A5D2F418D109AEEE6AFD342F3,6376,1681962386019
|
||||
c:/tmp/json/game_newsmithy.json,16F56B8C947046F74B4C26A5F397166,71058,1679909505402
|
||||
c:/tmp/json/game_opencond.json,4C5F1E1E948E5225EBB39F9D21ABA54,30507,1682218335508
|
||||
c:/tmp/json/game_pagoda.json,87BDDC4C718F59668B8DA177F46C97E,61205,1681962386215
|
||||
c:/tmp/json/game_pagodataskreward.json,E17D1136C63FA8D6C76A2156CD3D98,5033,1675761410655
|
||||
c:/tmp/json/game_pandamasbuff.json,76578B68014C5E6E68ACDB9E34D2391,1812,1677226965402
|
||||
c:/tmp/json/game_pandamasjs.json,666DA3906D124EEBCF28BAEC1BC82C6A,663,1680333520573
|
||||
c:/tmp/json/game_pandamasjx.json,A91343344FE7375FDCD1925EB11C718,26058,1681962386234
|
||||
c:/tmp/json/game_pandamasmryl.json,1D2FA4CD5CFE8FC162672643FA203B,1096,1682218335498
|
||||
c:/tmp/json/game_pandamasmz.json,3423EF4664A478E1FBCE8E72FB64C9,2676,1680144063145
|
||||
c:/tmp/json/game_pandamastj.json,8551DDDCE76239FC5D9319A302B29E7,15121,1681962386044
|
||||
c:/tmp/json/game_pandamastjjl.json,FC5542F0EC16DED5B9B49446601712BC,2583,1681962386031
|
||||
c:/tmp/json/game_pandamasyxjx.json,DD56E58FF48A953B7A8552ED3D73DB,1859,1679651030030
|
||||
c:/tmp/json/game_passcheck.json,EC66DF4C4EDDDAC32A16532C7F3E53FA,3782,1675761410751
|
||||
c:/tmp/json/game_paypackage.json,44618751217D9A12A93B56BBC3DD5BD,4952,1675761410750
|
||||
c:/tmp/json/game_playerinfor.json,8FC0A9B93292A9C7585ADD4ADAEE836,668,1678677255831
|
||||
c:/tmp/json/game_playerlv.json,80F2E314FA9E211248E289199A43D0E3,12102,1675761410657
|
||||
c:/tmp/json/game_potions.json,BC9A83E9E8A533A95FEA4CF018A57E0,16179,1681962386031
|
||||
c:/tmp/json/game_privilege.json,408075AFCCD9D1AACAB0323EC4F19624,33615,1676518692472
|
||||
c:/tmp/json/game_privilegecard.json,2128DDB5E7B8CB24770735FD42FF195,1059,1675761410742
|
||||
c:/tmp/json/game_rdtaskcondi.json,62A645F56868294B7426C923A26C58B1,90980,1682307537206
|
||||
c:/tmp/json/game_rdtasknpc.json,BF30AC2A685C4CC9F10ACD2736868,7382,1682307537148
|
||||
c:/tmp/json/game_recharge.json,D0D3904BF129EA74B7A7F27671FFFFA4,11867,1675761410742
|
||||
c:/tmp/json/game_reddot.json,55DF85673AF2532D1492D124AB83B26,1431,1675761410750
|
||||
c:/tmp/json/game_reddotgroup.json,356CDD66A5F22D349128653A45713,3999,1675761410751
|
||||
c:/tmp/json/game_reddottalkid.json,1BAC1E7B94AD24A6C48170811983DE98,1620,1675761410751
|
||||
c:/tmp/json/game_robot.json,3AE3B94AE169EA4113C089DC4FEF228,36683,1675761410337
|
||||
c:/tmp/json/game_sellcoefficient.json,64D33D5CCBFE5016BEE386D7EC334BE6,288,1680179912086
|
||||
c:/tmp/json/game_shop.json,EE68944972702EB5167AD131B8372D3,3900,1679296385073
|
||||
c:/tmp/json/game_shopitem.json,1668E6C4BA6B1B87214197FD3DE4E16,116423,1679296385064
|
||||
c:/tmp/json/game_show.json,65A4DF4CF97E22A3BF627EBFDC5B722A,1629,1681962386048
|
||||
c:/tmp/json/game_sign.json,D018C2FAF498486E33DE1898BEC246F,25295,1680256283923
|
||||
c:/tmp/json/game_signextra.json,75BB4F433524A45628F61282388EE5AD,2295,1680576438283
|
||||
c:/tmp/json/game_signreset.json,B458B081A4CB562EC14CC3B4374182C,129,1675761410740
|
||||
c:/tmp/json/game_skillafteratk.json,304A9C9CEEAD595D6F818646274FFF9,515714,1682307537190
|
||||
c:/tmp/json/game_skillatk.json,705ADAEFBE2F0B2C8E9DD4A5BC199FB,328331,1682307537244
|
||||
c:/tmp/json/game_skillbuff.json,F1439BBE20CC5027E4E3A48D222AF,77138,1682218335520
|
||||
c:/tmp/json/game_skillpassive.json,4F36F139285B29E968F324695DB52C0,48500,1681972759568
|
||||
c:/tmp/json/game_smithyatlas.json,53FD14E6C8EA11417227C3EA8965F6A,52402,1682218335520
|
||||
c:/tmp/json/game_smithyatlaslv.json,B5F2DC491CC7118EA2332FF129881B80,2609,1680179912086
|
||||
c:/tmp/json/game_smithyatlasscore.json,C9D57714FCA1018923141254BAC858,5778,1677038179702
|
||||
c:/tmp/json/game_smithycustomer.json,4033DFD1B47CA49DB811FFFFBB531E2,1515,1681126805545
|
||||
c:/tmp/json/game_smithyidtool.json,B98A8198519DFBCF82E73D8999F4AEDE,26469,1678157698235
|
||||
c:/tmp/json/game_smithymake.json,51109DA3B839B5C521CC453D3C152A6,470,1679906281635
|
||||
c:/tmp/json/game_smithymodelpool.json,6957C0A652F9524EA0E54797692B5056,147,1678073991461
|
||||
c:/tmp/json/game_smithyproficiency.json,BA7B4894161C7734FDC99548F9F387B4,144639,1681198061227
|
||||
c:/tmp/json/game_smithystovev1.json,77F6697AE5D6FE52030147B359851BD,3077,1681962386039
|
||||
c:/tmp/json/game_smithytask.json,63B5C31C1AEA89EBD14D9C1BF111C5AD,5109,1677059652991
|
||||
c:/tmp/json/game_smithytool.json,B98A8198519DFBCF82E73D8999F4AEDE,26469,1678157698232
|
||||
c:/tmp/json/game_talent.json,F641206D8EEBB6B46B76B2C8DC1FB2AF,16694,1681962386037
|
||||
c:/tmp/json/game_talentskill.json,8B9AE9E68EBFA10D0B750FD15F02C57,8991,1675761410715
|
||||
c:/tmp/json/game_taskactivereward.json,D3EED68F53E4C4B4365DE3B2157AC33E,841,1682307537206
|
||||
c:/tmp/json/game_taskround.json,9D2EE2F9BB90C79CDF713C94E57B5,3181,1682307537246
|
||||
c:/tmp/json/game_teaching.json,344348DE32EA83B05CADD5E36F2E5C59,15247,1680513216864
|
||||
c:/tmp/json/game_trollcoefficient.json,68CA578584F7C99B68FD9DBD2173F231,600,1675761410719
|
||||
c:/tmp/json/game_trollgoods.json,EBFCEB3737B0934D1CBD4934DDCA7AF0,6838,1676518692458
|
||||
c:/tmp/json/game_trolllv.json,7E33F3EEF3F139E0D276266448F3A52,1821,1675761410719
|
||||
c:/tmp/json/game_trollrule.json,ED2DAD2E962D3F4F5AC09081A75AFD,366,1675761410719
|
||||
c:/tmp/json/game_trolltrain.json,ADBA2BFEB89584A557A5ADCDB4EC334C,453,1675761410719
|
||||
c:/tmp/json/game_vikingboss.json,DB9954617885C974EC1F0AA23DCE676,67985,1682218335420
|
||||
c:/tmp/json/game_vikingbossskill.json,89C2DC9A201BBEA862C47636D29FCFA4,2382,1679296385065
|
||||
c:/tmp/json/game_vikingchallenge.json,4335C14D448FA128DB60BB96197CBC1D,1335,1675761410629
|
||||
c:/tmp/json/game_vikingentrance.json,5E40BF66B0F71B467B90D343F4991B,1124,1675761410612
|
||||
c:/tmp/json/game_vikinglineup.json,16A46E7023443832A8E258764C3083AD,4478,1675761410351
|
||||
c:/tmp/json/game_vip.json,78A863FC9926A02C9DEFD287102660,11859,1675761410755
|
||||
c:/tmp/json/game_worldall.json,FDE8BB284D535058DCAF3D30DC2C65C0,3426,1682218335506
|
||||
c:/tmp/json/game_worldbattle.json,43376C1582FA73922680BFBEB5314D6,2803,1680333520555
|
||||
c:/tmp/json/game_worldtask.json,A34A24C84F05C5826884E8B785FC2F7,24977,1682218335291
|
||||
F:/ExcelFile/Datas/__beans__.xlsx,D4BDC647431515D16B26347A8B898BAA,9417,1677038118101
|
||||
F:/ExcelFile/Datas/__enums__.xlsx,0E576421F2DC8B1F27CEEA3C0D2EDF9,18250,1681788582819
|
||||
F:/ExcelFile/Datas/__tables__.xlsx,B508BB5CBB19A68B0A6437062197F85,29114,1682303788395
|
||||
F:/ExcelFile/Datas/arena.xlsx,A971D35BFAA9E237658379B3DBBFD7E,23334,1679019552258
|
||||
F:/ExcelFile/Datas/battleready.xlsx,3B81C940FC86BD9FD74814608846D091,16352,1681380626795
|
||||
F:/ExcelFile/Datas/battletask_testing.xlsx,8DE417253683AFE8B4B9FEF829997F,9526,1677038117946
|
||||
F:/ExcelFile/Datas/breakingbad.xlsx,7CEA43D82E9CBDB8DAF8CB9EA2D7852,14672,1681380626787
|
||||
F:/ExcelFile/Datas/bubblegroup.xlsx,9DD28365735F480177E3F9616ECEFD,13536,1681903841630
|
||||
F:/ExcelFile/Datas/buzkashi.xlsx,96E69CA17FC147D6DB8E23940AFB32B,27104,1682317131873
|
||||
F:/ExcelFile/Datas/cardtalent.xlsx,126CF16B301DCD75264FAD6B12F48E,22408,1677038117896
|
||||
F:/ExcelFile/Datas/chat.xlsx,D66E7BC8566A2468C12F3B7733F64,20948,1677038118000
|
||||
F:/ExcelFile/Datas/com.xlsx,EE34D5438A70A5329324BC01CBAF18,29525,1682307439015
|
||||
F:/ExcelFile/Datas/combat.xlsx,CE70D5448F3B6B3E6CB3E6C761F6827,18533,1678676490311
|
||||
F:/ExcelFile/Datas/drawcard.xlsx,AB35A77042330EC1A14EAB7A9E28B6F,16729,1681788588866
|
||||
F:/ExcelFile/Datas/dreamland.xlsx,40C56DCB3D4FD3ECAFFD3E8872193E6,13781,1677038117902
|
||||
F:/ExcelFile/Datas/drop.xlsx,608CDC2BE7F5865C2793FD8F72BA1C4,21617,1677661861014
|
||||
F:/ExcelFile/Datas/enchantboss.xlsx,8E87EEDEF557483587854588BA3238FA,21876,1677038117903
|
||||
F:/ExcelFile/Datas/equip.xlsx,35C2E3B648AAE06A3611FC1C65BBD46,170894,1680333504643
|
||||
F:/ExcelFile/Datas/extservers.xlsx,C7E29E9F823E9A3923B9AE8B33C09136,12436,1677038117894
|
||||
F:/ExcelFile/Datas/facemod.xlsx,BBDEC392FF72E37D6DCAAAC5B35F8A2,10903,1677038118103
|
||||
F:/ExcelFile/Datas/favorability.xlsx,A3FB4AEA4B5C7E20212E6FF37D25B9F3,36061,1682214557100
|
||||
F:/ExcelFile/Datas/fightevent.xlsx,83E41BCD5E8A81D86CB749176188E,15642,1677038117914
|
||||
F:/ExcelFile/Datas/getresource.xlsx,D9F0FB7515464729A313A3485271A9,10963,1677038118091
|
||||
F:/ExcelFile/Datas/GM.xlsx,292F51BEF6314DF4C794E367CF7939D,13106,1681903841561
|
||||
F:/ExcelFile/Datas/gourmet.xlsx,3DC05C0642437F7F94C26CADE35E5E,19282,1677038118025
|
||||
F:/ExcelFile/Datas/growthtask.xlsx,39F2BA8B3DA4F14C66B50131924A19,16705,1677038117911
|
||||
F:/ExcelFile/Datas/guide.xlsx,CB2C2A7F9156BEFEEFFC0ACDBD3CE,191261,1680157040368
|
||||
F:/ExcelFile/Datas/guild.xlsx,D56B29EBF6811F4615E56C908E4D85,17769,1677038117948
|
||||
F:/ExcelFile/Datas/guildboss.xlsx,D84314DFB6E69D93CB68F35292A6BBA,59077,1677038117940
|
||||
F:/ExcelFile/Datas/help_information.xlsx,5E641942C5D9BE65334AFE37CB97E7,9438,1677038118061
|
||||
F:/ExcelFile/Datas/hero_awaken.xlsx,17241886F99CA6D9C2DE6CBD8535EE8,66257,1677038118043
|
||||
F:/ExcelFile/Datas/hero_method.xlsx,50AEF20FC5EB9DF8A822632FE39979,15330,1677038118002
|
||||
F:/ExcelFile/Datas/hero.xlsx,B0E9375A5937E64AB754AF175CD8B85E,96091,1681788588901
|
||||
F:/ExcelFile/Datas/herofusion.xlsx,5A4C6E879DFAA6B3AD8AFD26B0B65BA7,12628,1677038118049
|
||||
F:/ExcelFile/Datas/horoscope.xlsx,9560CD4D77B1BD959A6460837913BF45,47327,1677038118035
|
||||
F:/ExcelFile/Datas/hunting.xlsx,4643CAC69D2E962FB3F3BAF5B0B1CCF0,21253,1682068376991
|
||||
F:/ExcelFile/Datas/item.xlsx,F81D226679D35BFDFB4818175B1E63A,55010,1682307439025
|
||||
F:/ExcelFile/Datas/itinerant_trader.xlsx,4B3E519775EED285CD2C882EAEBD,22379,1681380626777
|
||||
F:/ExcelFile/Datas/jump.xlsx,44C6C4C582EC22B979DB9BD934AC9D3,22284,1682214557119
|
||||
F:/ExcelFile/Datas/library.xlsx,4DAB219F3139FF5A94D1ACA845B7E66,75318,1677038118003
|
||||
F:/ExcelFile/Datas/linestory.xlsx,8B252F3D12CEEEA7FFA57735E26986,16205,1682317127037
|
||||
F:/ExcelFile/Datas/Localize.csv,61639A33195FC94FABF595F3BD822F,873133,1682303788392
|
||||
F:/ExcelFile/Datas/Lottery.xlsx,A426E6D87B67F955768D79918E5C25C,13931,1681380626798
|
||||
F:/ExcelFile/Datas/mail.xlsx,22DBD9DFE47AD018BC981A1FCE23D6,12780,1678271305434
|
||||
F:/ExcelFile/Datas/mainchapter.xlsx,FDD3A1CFE335DA11B9516DED3CA41C,28048,1681962396011
|
||||
F:/ExcelFile/Datas/material.xlsx,1B4452105322F2851B79F8A589B13D1,14554,1681788588657
|
||||
F:/ExcelFile/Datas/model.xlsx,E5FB152AF7EA88EC88278E7B985C321,32122,1682214557104
|
||||
F:/ExcelFile/Datas/monster.xlsx,26A9EEF5D3319C7E77DA58320C2D477,51115,1678676490314
|
||||
F:/ExcelFile/Datas/monsterformat.xlsx,39C7267D148F9882A4AAAA112CC946,333861,1682068376989
|
||||
F:/ExcelFile/Datas/msgdistrib.xlsx,EF1B57E58F1C495F531EA37428622,10747,1681962396033
|
||||
F:/ExcelFile/Datas/name.xlsx,A88D302B5F4EFDD8506F867673722965,16331,1677038118083
|
||||
F:/ExcelFile/Datas/navigation.xlsx,E4EDBE2E5D78429D8D53B7C27778A94,10762,1681962396025
|
||||
F:/ExcelFile/Datas/newsmithy.xlsx,7EF071F9FBF8A14EAA780ED2BC019E8,93682,1682068377027
|
||||
F:/ExcelFile/Datas/opencond.xlsx,DF197291CADAEEEF25D7C068F6132964,23293,1682214557117
|
||||
F:/ExcelFile/Datas/pandamas.xlsx,383DF17FD28ED4650B1C94EAB6AC4ED,63321,1682214557102
|
||||
F:/ExcelFile/Datas/passcheck.xlsx,4D1386149C340606EE1FB55A018267B,11975,1677038118024
|
||||
F:/ExcelFile/Datas/paypackage.xlsx,4F18D9D87B17217FF83C7ACBF17267EE,12232,1677038118066
|
||||
F:/ExcelFile/Datas/playerinfor.xlsx,181D7352304826D16F43633134C12AC3,12730,1678676490294
|
||||
F:/ExcelFile/Datas/playerlv.xlsx,E975DF92CF2E69D68F82529E7780,12099,1677038117951
|
||||
F:/ExcelFile/Datas/privilegecard.xlsx,5935A3E0A03F2FA15D245F407C8E3CA5,18057,1677038117888
|
||||
F:/ExcelFile/Datas/recharge.xlsx,698CA16B364BB252579F26FDCA82F8B3,13582,1677038118050
|
||||
F:/ExcelFile/Datas/reddot.xlsx,63127E7F948ECDA8E33D9D38BCA7A4,26327,1681788588661
|
||||
F:/ExcelFile/Datas/robot.xlsx,1615F3DB6FC51B61711110A3CFE06F5F,20979,1677038118098
|
||||
F:/ExcelFile/Datas/shop.xlsx,D1387DE5C698B6B634D148AEB8E9C4,44737,1679019552256
|
||||
F:/ExcelFile/Datas/show.xlsx,2B3B56FAB738CE6F3A86A0A5291E53B0,14266,1681788588658
|
||||
F:/ExcelFile/Datas/sign.xlsx,D8AFDD1D85A33929EA4C473355D6BD,20011,1680576410799
|
||||
F:/ExcelFile/Datas/skill.xlsx,1E85246915772B48DFECF16D2B5822,235430,1682307439024
|
||||
F:/ExcelFile/Datas/task.xlsx,5348EE0BFE6BE40660944690CDDDA,17151,1682303788398
|
||||
F:/ExcelFile/Datas/taskcond.xlsx,6BB5303F22FE748B3476388F532656A0,131959,1682303788407
|
||||
F:/ExcelFile/Datas/teaching.xlsx,FEE01F38DBFDC6FC926469C898D546D,20921,1680511806575
|
||||
F:/ExcelFile/Datas/trolltrain.xlsx,421BDCBB1DBC58C13A639CD69499463F,25782,1677038117892
|
||||
F:/ExcelFile/Datas/ui.xlsx,C8FF882D450B126913D7E8AA59869F6,38692,1682307439018
|
||||
F:/ExcelFile/Datas/vikingexpedition.xlsx,101469EDC4A8C2E54A98ACAC329F471,31312,1682068376993
|
||||
F:/ExcelFile/Datas/vip.xlsx,D195DACDCEFF7989D716F27CDFF265,11585,1677038117949
|
||||
F:/ExcelFile/Datas/worldtask.xlsx,26498DFACA9EA6B2488014C08664A9B4,273076,1682303788405
|
||||
F:/ExcelFile/Defines/enum.xml,BDB90FEDFC1ECF9669D632BC75EB871,660,1677225663180
|
||||
F:/ExcelFile/Defines/format.xml,7E89E7E9857E207BA482E9A078B98012,1634,1682307526410
|
||||
F:/ExcelFile/Defines/LocalizeParam.xml,5577C9C3A9218B6B26E1D78F526C05E,425,1677038122208
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/__beans__.xlsx,D4BDC647431515D16B26347A8B898BAA,9417,1660808890718
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/__enums__.xlsx,309DCDBBFF11E490D1707F285F63E0F8,18121,1671613786463
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/arena.xlsx,BAFB5448ECA3AF1573E62EFF7462F41,22207,1675669257601
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/battleready.xlsx,ABCC4EC351DF5B2F773D4FA55EDBAD,12361,1675993782723
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/battletask_testing.xlsx,8DE417253683AFE8B4B9FEF829997F,9526,1673334891747
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/cardtalent.xlsx,126CF16B301DCD75264FAD6B12F48E,22408,1675913355296
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/chat.xlsx,D66E7BC8566A2468C12F3B7733F64,20948,1672277335433
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/combat.xlsx,BB13F148B01C8274F29D4A39BEC5822,18173,1675669257605
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/dreamland.xlsx,40C56DCB3D4FD3ECAFFD3E8872193E6,13781,1675669257615
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/drop.xlsx,7CBB387AE913F4EBDC4CC12C9E3CFF,21834,1672384451999
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/enchantboss.xlsx,8E87EEDEF557483587854588BA3238FA,21876,1675669257617
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/equip.xlsx,B48A32328A57B8DFDBAB472F1A713,131355,1673751444962
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/extservers.xlsx,C7E29E9F823E9A3923B9AE8B33C09136,12436,1676354566699
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/facemod.xlsx,BBDEC392FF72E37D6DCAAAC5B35F8A2,10903,1658742301043
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/fightevent.xlsx,83E41BCD5E8A81D86CB749176188E,15642,1675131784842
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/getresource.xlsx,D9F0FB7515464729A313A3485271A9,10963,1661996705967
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/GM.xlsx,FF4B80E53432F05F523E98B7CDBF553,13040,1672305401438
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/gourmet.xlsx,3DC05C0642437F7F94C26CADE35E5E,19282,1671071006973
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/growthtask.xlsx,39F2BA8B3DA4F14C66B50131924A19,16705,1675131784795
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/guide.xlsx,9F85E5EDEB6D14BAB03C7EF6BFAF4A15,192663,1675131784802
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/guild.xlsx,D56B29EBF6811F4615E56C908E4D85,17769,1672991443412
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/guildboss.xlsx,D84314DFB6E69D93CB68F35292A6BBA,59077,1673767098700
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/help_information.xlsx,5E641942C5D9BE65334AFE37CB97E7,9438,1667958528956
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/hero_awaken.xlsx,17241886F99CA6D9C2DE6CBD8535EE8,66257,1669600775287
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/hero_method.xlsx,50AEF20FC5EB9DF8A822632FE39979,15330,1672035654186
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/herofusion.xlsx,5A4C6E879DFAA6B3AD8AFD26B0B65BA7,12628,1669280521033
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/horoscope.xlsx,9560CD4D77B1BD959A6460837913BF45,47327,1669868288742
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/hunting.xlsx,05C744CAB98DC8320579AF37AF187D6,20981,1675669257618
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/ip.xlsx,FCECF489FCBA09B725F9E6E5D5CEC5,12662,1663813033423
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/item.xlsx,0E3EDBA2B4D38FEADC2CC6AFDD448C0,46269,1675913355299
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/jump.xlsx,2E50FDED7221E4C9B67442551642426,23695,1673751445047
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/kungfu.xlsx,80D3E1ECC8D4BD72BD89B227E46E2E,21553,1673866895198
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/library.xlsx,4DAB219F3139FF5A94D1ACA845B7E66,75318,1672024001073
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/linestory.xlsx,8B252F3D12CEEEA7FFA57735E26986,16205,1672384451890
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/link.xlsx,5BA9EDFBF08BE01EB747E727AE2DC2CE,11025,1661996705968
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/mail.xlsx,EEA346AAE7AD69A16ECE0E3C0711FE,12251,1671071006947
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/mainchapter.xlsx,FE1BFBAFDADF8A649D1F67CED92A81,26062,1675669257620
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/mainline.xlsx,56A852F51BACF1F8D9A0F5FF24D08617,76018,1675669257622
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/model.xlsx,52773FF8F8493E47C832D47D6EB1F77,30604,1676517068465
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/monster.xlsx,A0B42C273AB4A932D92DD921AA1DA,47838,1672483211595
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/monsterformat.xlsx,7FBBEB8C9286E77B0C89E827FA4B0B3,304998,1673780060731
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/msgdistrib.xlsx,AF26182EB1CC72F5D1D81570BF84BF,10579,1673334891672
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/name.xlsx,A88D302B5F4EFDD8506F867673722965,16331,1664157402399
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/opencond.xlsx,D2497F3EFE5A1BD594A213882034942,21782,1676450811409
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/pagoda.xlsx,627839BC2E575B19543AB566FF94E338,34234,1675669257624
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/passcheck.xlsx,4D1386149C340606EE1FB55A018267B,11975,1671071006955
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/paypackage.xlsx,4F18D9D87B17217FF83C7ACBF17267EE,12232,1667895839191
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/playerinfor.xlsx,721CF8DD63721771C96BC681623C1F30,13375,1666145807176
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/playerlv.xlsx,E975DF92CF2E69D68F82529E7780,12099,1672819357711
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/privilegecard.xlsx,5935A3E0A03F2FA15D245F407C8E3CA5,18057,1676517068473
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/recharge.xlsx,698CA16B364BB252579F26FDCA82F8B3,13582,1669028376674
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/reddot.xlsx,98A552AFD8B11EA810C323A9858BAD63,20963,1672281763834
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/robot.xlsx,1615F3DB6FC51B61711110A3CFE06F5F,20979,1661407782710
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/shop.xlsx,C58B4394938145682CBDE40D1DAD8A,40598,1676517172729
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/show.xlsx,734A5C1D26E8995F0734B91B62EC7BB,13532,1673675480748
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/sign.xlsx,4BAED0425653ED914922C9B3592E9387,15828,1672384452018
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/skill.xlsx,41D26F1FE8F76C0FA53CBD8E9901FF9,237716,1675913355307
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/smithy.xlsx,D5BF684A6B44EA51B2EBFCF76122E6A3,18677,1672384452047
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/stroy.xlsx,C4EBEAB24A57EE48F75AD7677A79E879,98906,1666856824641
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/task.xlsx,6677CB7FA05294B14E93907751DA80F6,28349,1673408491101
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/taskcond.xlsx,E1F8F4A0EC9CF0A698285DBB67239642,49367,1675669257587
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/teaching.xlsx,7C76799E9162FDAA959B972E0149F8,17032,1676517172738
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/trolltrain.xlsx,421BDCBB1DBC58C13A639CD69499463F,25782,1676517172739
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/vikingexpedition.xlsx,D4BCB092EA2B3028BAFBCA0DA873DEA,30286,1675669257625
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Datas/vip.xlsx,D195DACDCEFF7989D716F27CDFF265,11585,1672819357705
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Defines/enum.xml,32A3B669765E7B9E3EED389AFE70FDCF,507,1675132985754
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Defines/format.xml,DBD3E217262D1DCFE0E65373A0317790,1117,1675132685762
|
||||
F:/svn/dreamworks/client/dreamworks/ExcelFile/Defines/LocalizeParam.xml,5577C9C3A9218B6B26E1D78F526C05E,425,1658195443477
|
8
cmd/v2/FyneApp.toml
Normal file
8
cmd/v2/FyneApp.toml
Normal file
@ -0,0 +1,8 @@
|
||||
Website = "http://legu.cc"
|
||||
|
||||
[Details]
|
||||
Icon = "app.png"
|
||||
Name = "RobotGUI"
|
||||
ID = "cc.legu.app"
|
||||
Version = "1.2.17"
|
||||
Build = 50
|
BIN
cmd/v2/app.png
Normal file
BIN
cmd/v2/app.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
7
cmd/v2/build.bat
Normal file
7
cmd/v2/build.bat
Normal file
@ -0,0 +1,7 @@
|
||||
@echo off
|
||||
|
||||
set input=%1%
|
||||
|
||||
echo build version:%input%
|
||||
|
||||
fyne package --name RobotGUI-%input% -os windows
|
42
cmd/v2/gen_test.go
Normal file
42
cmd/v2/gen_test.go
Normal file
@ -0,0 +1,42 @@
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
cfg "go_dreamfactory/sys/configure/structs"
|
||||
"html/template"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type TaskCond struct {
|
||||
Data map[int32]*cfg.GameRdtaskCondiData
|
||||
}
|
||||
|
||||
func TestTask(t *testing.T) {
|
||||
commcfg := &common.Config{
|
||||
Path: "F:\\projects\\workspace\\go_dreamfactory\\bin\\json",
|
||||
}
|
||||
if tb, err := cfg.NewTables(commcfg.Loader); err == nil {
|
||||
data := tb.RdtaskCondi.GetDataMap()
|
||||
|
||||
tmpl := template.New("task")
|
||||
tplTxt := `reqDataMap := map[int32]TaskCondi{
|
||||
{{ range .Data }}
|
||||
{{.Id}}:{ {{.Type}},[]int32{ {{.Data1}},{{.Data2}},{{.Data3}},{{.Data4}},{{.Data5}} },
|
||||
{{ end}} }`
|
||||
|
||||
tpl, err := tmpl.Parse(tplTxt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
//输出文件
|
||||
file, err := os.OpenFile("./tpl.txt", os.O_CREATE|os.O_WRONLY, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
p := TaskCond{
|
||||
Data: data,
|
||||
}
|
||||
tpl.Execute(file, p)
|
||||
}
|
||||
}
|
BIN
cmd/v2/icon.png
Normal file
BIN
cmd/v2/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 51 KiB |
304
cmd/v2/lib/assistant.go
Normal file
304
cmd/v2/lib/assistant.go
Normal file
@ -0,0 +1,304 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
"go_dreamfactory/pb"
|
||||
"math"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type assistant struct {
|
||||
timeout time.Duration //处理超时时间
|
||||
lps uint32 //每秒请求量
|
||||
duration time.Duration //持续时间
|
||||
concurrency uint32 //并发量
|
||||
|
||||
ctx context.Context
|
||||
callCount int64 //调用次数,每次启动时重置
|
||||
|
||||
goPool GoPool //携程池
|
||||
cancelFunc context.CancelFunc //取消
|
||||
caller Handler //处理器
|
||||
status uint32 //状态
|
||||
resultCh chan *CallResult //调用结果
|
||||
obs observer.Observer
|
||||
}
|
||||
|
||||
func NewAssistant(obs observer.Observer, pm ParamMgr) (Aiassistant, error) {
|
||||
|
||||
if err := pm.Check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
a := &assistant{
|
||||
timeout: pm.Timeout,
|
||||
lps: pm.Lps,
|
||||
duration: pm.Duration,
|
||||
caller: pm.Caller,
|
||||
status: STATUS_ORIGINAL,
|
||||
resultCh: pm.ResultCh,
|
||||
obs: obs,
|
||||
}
|
||||
if err := a.init(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (a *assistant) init() error {
|
||||
logrus.Debug("AI助手初始化")
|
||||
//并发量的计算
|
||||
//并发量 ≈ 超时时间 / 发送的间隔时间
|
||||
var total = int64(a.timeout)/int64(1e9/a.lps) + 1
|
||||
if total > math.MaxInt32 {
|
||||
total = math.MaxInt32
|
||||
}
|
||||
|
||||
a.concurrency = uint32(total)
|
||||
gp, err := NewGoPool(a.concurrency)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.goPool = gp
|
||||
logrus.WithField("并发量", a.concurrency).Debug("AI助手初始化完成 ")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *assistant) callOne(req *RawReq) *RawResp {
|
||||
atomic.AddInt64(&a.callCount, 1)
|
||||
logrus.WithField("count", &a.callCount).WithField("Len", len(req.Req)).Debug("调用协议")
|
||||
if req == nil {
|
||||
return &RawResp{ID: -1, Err: errors.New("无效的请求")}
|
||||
}
|
||||
var rawResp RawResp
|
||||
start := time.Now().UnixNano()
|
||||
resp, err := a.caller.Call(req.Req)
|
||||
end := time.Now().UnixNano()
|
||||
elapsedTime := time.Duration(end - start)
|
||||
if err != nil {
|
||||
errMsg := fmt.Sprintf("调用失败: %v", err)
|
||||
rawResp = RawResp{
|
||||
ID: req.ID,
|
||||
Err: errors.New(errMsg),
|
||||
Elapse: elapsedTime,
|
||||
}
|
||||
} else {
|
||||
rawResp = RawResp{
|
||||
ID: req.ID,
|
||||
Resp: resp,
|
||||
Elapse: elapsedTime,
|
||||
}
|
||||
}
|
||||
return &rawResp
|
||||
}
|
||||
|
||||
// 异步调用接口
|
||||
func (a *assistant) asyncCall() {
|
||||
a.goPool.Take()
|
||||
go func() {
|
||||
defer func() {
|
||||
if p := recover(); p != nil {
|
||||
err, ok := interface{}(p).(error)
|
||||
var errMsg string
|
||||
if ok {
|
||||
errMsg = fmt.Sprintf("Async Call Panic! (error: %s)", err)
|
||||
} else {
|
||||
errMsg = fmt.Sprintf("Async Call Panic! (clue: %#v)", p)
|
||||
}
|
||||
logrus.Errorln(errMsg)
|
||||
result := &CallResult{
|
||||
Id: -1,
|
||||
Code: RES_CODE_FATAL_CALL,
|
||||
Message: errMsg,
|
||||
}
|
||||
a.sendResult(result)
|
||||
}
|
||||
a.goPool.Return()
|
||||
}()
|
||||
|
||||
req := a.caller.BuildReq()
|
||||
if req.ID == 0 {
|
||||
return
|
||||
}
|
||||
//调用状态 0未调用 1调用结束 2调用超时
|
||||
var callStatus uint32
|
||||
|
||||
// 超时处理
|
||||
timer := time.AfterFunc(a.timeout, func() {
|
||||
if !atomic.CompareAndSwapUint32(&callStatus, 0, 2) {
|
||||
return
|
||||
}
|
||||
|
||||
result := &CallResult{
|
||||
Id: req.ID,
|
||||
Req: req,
|
||||
Code: RES_CODE_CALL_TIMEOUT,
|
||||
Message: fmt.Sprintf("超时,期望小于 %v", a.timeout),
|
||||
Elapse: a.timeout,
|
||||
}
|
||||
a.sendResult(result)
|
||||
})
|
||||
resp := a.callOne(&req)
|
||||
|
||||
logrus.WithField("耗时", resp.Elapse).Debug("实际耗时")
|
||||
if !atomic.CompareAndSwapUint32(&callStatus, 0, 1) {
|
||||
return
|
||||
}
|
||||
|
||||
timer.Stop()
|
||||
|
||||
var result *CallResult
|
||||
if resp.Err != nil {
|
||||
result = &CallResult{
|
||||
Id: req.ID,
|
||||
Req: req,
|
||||
Code: RES_CODE_ERROR_CALL,
|
||||
Message: resp.Err.Error(),
|
||||
Elapse: resp.Elapse,
|
||||
}
|
||||
} else {
|
||||
result = a.caller.Check(req, *resp)
|
||||
result.Elapse = resp.Elapse
|
||||
}
|
||||
a.sendResult(result)
|
||||
}()
|
||||
}
|
||||
|
||||
// 停止发送
|
||||
func (a *assistant) prepareStop(ctxErr error) {
|
||||
logrus.WithField("cause", ctxErr).Info("准备停止")
|
||||
atomic.CompareAndSwapUint32(&a.status, STATUS_STARTED, STATUS_STOPPING)
|
||||
logrus.Debug("关闭结果通道")
|
||||
close(a.resultCh)
|
||||
atomic.StoreUint32(&a.status, STATUS_STOPPED)
|
||||
}
|
||||
|
||||
// 发送请求即调用接口
|
||||
func (a *assistant) handleReq(throttle <-chan time.Time) {
|
||||
for {
|
||||
select {
|
||||
case <-a.ctx.Done():
|
||||
a.prepareStop(a.ctx.Err())
|
||||
return
|
||||
default:
|
||||
}
|
||||
a.asyncCall()
|
||||
if a.lps > 0 {
|
||||
select {
|
||||
case <-throttle:
|
||||
case <-a.ctx.Done():
|
||||
a.prepareStop(a.ctx.Err())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *assistant) sendResult(result *CallResult) bool {
|
||||
if atomic.LoadUint32(&a.status) != STATUS_STARTED {
|
||||
a.printResult(result, "已停止")
|
||||
return false
|
||||
}
|
||||
select {
|
||||
case a.resultCh <- result:
|
||||
return true
|
||||
default:
|
||||
a.printResult(result, "结果通道已满")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (a *assistant) printResult(result *CallResult, cause string) {
|
||||
resultMsg := fmt.Sprintf(
|
||||
"Id:%d,Code=%d,Msg=%s,Elapse=%v",
|
||||
result.Id, result.Code, result.Message, result.Elapse)
|
||||
logrus.Warnf("result:%s (cause:%s)", resultMsg, cause)
|
||||
}
|
||||
|
||||
// 启动AI助手
|
||||
func (a *assistant) Start() bool {
|
||||
logrus.Debug("AI助手启动")
|
||||
|
||||
// 节流 周期性向目标发送
|
||||
var throttle <-chan time.Time
|
||||
if a.lps > 0 {
|
||||
//间隔时间
|
||||
interval := time.Duration(1e9 / a.lps)
|
||||
logrus.Debugf("启动节流控制 间隔: %v", interval)
|
||||
throttle = time.Tick(interval)
|
||||
}
|
||||
|
||||
// 初始化上下文和设置取消函数
|
||||
a.ctx, a.cancelFunc = context.WithTimeout(context.Background(), a.duration)
|
||||
|
||||
// 重置调用次数
|
||||
a.callCount = 0
|
||||
|
||||
// 设置状态为已启动
|
||||
atomic.StoreUint32(&a.status, STATUS_STARTED)
|
||||
|
||||
go func() {
|
||||
logrus.Debug("请求处理中...")
|
||||
a.handleReq(throttle)
|
||||
logrus.Infof("停止 调用次数:%d", a.callCount)
|
||||
}()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// 手动停止
|
||||
func (a *assistant) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *assistant) ShowResult() {
|
||||
statistics := &Statistics{}
|
||||
max := statistics.MaxElapse
|
||||
min := statistics.MinElapse
|
||||
|
||||
for r := range a.resultCh {
|
||||
if r.Code != RES_CODE_SUCCESS {
|
||||
logrus.WithField("result", r.Code).Debug("失败的结果")
|
||||
continue
|
||||
}
|
||||
msg := &pb.UserMessage{}
|
||||
// logrus.Debugf("结果字节长度 %d", len(r.Resp.Resp))
|
||||
if err := proto.Unmarshal(r.Resp.Resp, msg); err != nil {
|
||||
logrus.Error("结果解析失败")
|
||||
continue
|
||||
}
|
||||
// 协议名
|
||||
statistics.Route = fmt.Sprintf("%s.%s", msg.MainType, msg.SubType)
|
||||
// 总耗时
|
||||
statistics.ElapseTotal += float64(r.Elapse.Nanoseconds())
|
||||
|
||||
if float64(r.Elapse.Nanoseconds()) > max {
|
||||
max = float64(r.Elapse.Nanoseconds())
|
||||
} else {
|
||||
min = float64(r.Elapse.Nanoseconds())
|
||||
}
|
||||
logrus.WithFields(logrus.Fields{"mainType": msg.MainType, "subType": msg.SubType, "耗时": r.Elapse}).Info("结果")
|
||||
}
|
||||
if a.callCount == 1 {
|
||||
min = max
|
||||
}
|
||||
// 调用次数
|
||||
statistics.CallCount = a.callCount
|
||||
statistics.ElapseTotal = common.FormatFloatCommon(statistics.ElapseTotal / 1e6)
|
||||
statistics.MaxElapse = common.FormatFloatCommon(max / 1e6)
|
||||
statistics.MinElapse = common.FormatFloatCommon(min / 1e6)
|
||||
//平均耗时=总耗时/调用次数
|
||||
statistics.AvgElapse = common.FormatFloatCommon(statistics.ElapseTotal / float64(statistics.CallCount))
|
||||
|
||||
a.obs.Notify(observer.EVENT_RESULT, statistics)
|
||||
}
|
40
cmd/v2/lib/base.go
Normal file
40
cmd/v2/lib/base.go
Normal file
@ -0,0 +1,40 @@
|
||||
package lib
|
||||
|
||||
import "time"
|
||||
|
||||
type RawReq struct {
|
||||
ID int64
|
||||
Req []byte
|
||||
}
|
||||
|
||||
type RawResp struct {
|
||||
ID int64
|
||||
Resp []byte
|
||||
Err error
|
||||
Elapse time.Duration
|
||||
}
|
||||
|
||||
type ResCode int
|
||||
|
||||
const (
|
||||
RES_CODE_SUCCESS ResCode = 0 //成功
|
||||
RES_CODE_CALL_TIMEOUT = 1001 //调用超时
|
||||
RES_CODE_ERROR_CALL = 2001 // 调用错误
|
||||
RES_CODE_ERROR_RESPONSE = 2002 // 响应错误
|
||||
RES_CODE_ERROR_CALEE = 2003 // 被测软件内部错误
|
||||
RES_CODE_FATAL_CALL = 3001 // 调用过程中发生了致命错误!
|
||||
)
|
||||
|
||||
//助手执行状态
|
||||
const (
|
||||
// 原始状态
|
||||
STATUS_ORIGINAL uint32 = 0
|
||||
// 正在启动
|
||||
STATUS_STARTING uint32 = 1
|
||||
//已启动
|
||||
STATUS_STARTED uint32 = 2
|
||||
//正在停止
|
||||
STATUS_STOPPING uint32 = 3
|
||||
// 已停止
|
||||
STATUS_STOPPED uint32 = 4
|
||||
)
|
27
cmd/v2/lib/common/constant.go
Normal file
27
cmd/v2/lib/common/constant.go
Normal file
@ -0,0 +1,27 @@
|
||||
package common
|
||||
|
||||
type (
|
||||
WindowAspect int64
|
||||
WindowMode int64
|
||||
WindowAction int64
|
||||
)
|
||||
|
||||
const (
|
||||
MainType = "mainType"
|
||||
SubType = "subType"
|
||||
Params = "params"
|
||||
)
|
||||
|
||||
const (
|
||||
WindowAspect_Normal WindowAspect = iota
|
||||
WindowAspect_FullScreen
|
||||
)
|
||||
|
||||
const (
|
||||
DEFAULT_RESOURCE_PATH = "resources"
|
||||
)
|
||||
|
||||
const (
|
||||
CONFIG_SERVICE_NAME = "name"
|
||||
CONFIG_SERVICE_URL = "url"
|
||||
)
|
241
cmd/v2/lib/common/itemlist.go
Normal file
241
cmd/v2/lib/common/itemlist.go
Normal file
@ -0,0 +1,241 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go_dreamfactory/utils"
|
||||
"io/ioutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ItemList struct {
|
||||
SelItemIds []string //选择的ID 多选
|
||||
SelItemId string //选择的ID 单选
|
||||
ItemTotal int //总数
|
||||
TitleLabel *widget.Label
|
||||
CachedList List
|
||||
ItemList *widget.List
|
||||
SearchItem []Item //用于暂存搜索结果
|
||||
}
|
||||
|
||||
func NewItemList() *ItemList {
|
||||
return &ItemList{
|
||||
TitleLabel: &widget.Label{},
|
||||
CachedList: NewList(""),
|
||||
}
|
||||
}
|
||||
|
||||
// 重置
|
||||
func (f *ItemList) Reset() {
|
||||
f.ItemTotal = 0
|
||||
f.SelItemIds = []string{}
|
||||
f.SelItemId = ""
|
||||
f.CachedList = NewList("")
|
||||
f.ItemList.Refresh()
|
||||
}
|
||||
|
||||
func (f *ItemList) CreateList() *widget.List {
|
||||
f.ItemList = widget.NewList(
|
||||
func() int {
|
||||
return len(f.CachedList.Items)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return widget.NewLabel("Template")
|
||||
},
|
||||
func(id widget.ListItemID, item fyne.CanvasObject) {
|
||||
c, _ := item.(*widget.Label)
|
||||
c.Text = f.CachedList.Items[id].Text
|
||||
c.Refresh()
|
||||
},
|
||||
)
|
||||
f.ItemList.OnSelected = func(id widget.ListItemID) {
|
||||
selId := f.CachedList.Items[id].Id
|
||||
f.SelItemId = selId
|
||||
return
|
||||
}
|
||||
|
||||
// f.ItemList.OnUnselected = func(id widget.ListItemID) {
|
||||
// selId := f.CachedList.Items[id].Id
|
||||
// utils.DeleteString(f.SelItemIds, selId)
|
||||
// }
|
||||
return f.ItemList
|
||||
}
|
||||
|
||||
// 创建默认的列表
|
||||
func (f *ItemList) CreateDefaultCheckList() *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)
|
||||
_id := f.CachedList.Items[id].Id
|
||||
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, _id)
|
||||
} else {
|
||||
f.SelItemIds = utils.DeleteString(f.SelItemIds, _id)
|
||||
}
|
||||
f.TitleLabel.SetText(fmt.Sprintf("(%d/%d)", len(f.SelItemIds), f.ItemTotal))
|
||||
f.CachedList.Items[id].Checked = b
|
||||
// sort.Sort(f.cachedList)
|
||||
f.ItemList.Refresh()
|
||||
}
|
||||
c.Refresh()
|
||||
},
|
||||
)
|
||||
return f.ItemList
|
||||
}
|
||||
|
||||
// 创建下载列表
|
||||
func (f *ItemList) CreateDownloadList() *widget.List {
|
||||
f.ItemList = widget.NewList(
|
||||
func() int {
|
||||
return len(f.CachedList.Items)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
chk := widget.NewCheck("Template", func(bool) {})
|
||||
lb := widget.NewLabel("Template")
|
||||
items := container.NewHBox(chk, &layout.Spacer{}, lb)
|
||||
return items
|
||||
},
|
||||
func(id widget.ListItemID, item fyne.CanvasObject) {
|
||||
c, _ := item.(*fyne.Container)
|
||||
chk := c.Objects[0].(*widget.Check)
|
||||
data := f.CachedList.Items[id]
|
||||
chk.Text = data.Text
|
||||
chk.Checked = data.Checked
|
||||
chk.OnChanged = func(b bool) {
|
||||
if b {
|
||||
f.SelItemIds = append(f.SelItemIds, chk.Text)
|
||||
} else {
|
||||
f.SelItemIds = utils.DeleteString(f.SelItemIds, chk.Text)
|
||||
}
|
||||
f.CachedList.Items[id].Checked = b
|
||||
// sort.Sort(f.cachedList)
|
||||
f.ItemList.Refresh()
|
||||
}
|
||||
|
||||
lb := c.Objects[2].(*widget.Label)
|
||||
lb.Text = ConvertFileSize(data.Size)
|
||||
c.Refresh()
|
||||
},
|
||||
)
|
||||
return f.ItemList
|
||||
}
|
||||
|
||||
func (f *ItemList) AddItem(item Item) {
|
||||
f.CachedList.Items = append(f.CachedList.Items, item)
|
||||
// sort.Sort(f.cachedList)
|
||||
f.ItemList.Refresh()
|
||||
}
|
||||
|
||||
func (f *ItemList) AddItemWithText(val string) {
|
||||
val = strings.TrimSpace(val)
|
||||
if len(val) == 0 {
|
||||
return
|
||||
}
|
||||
newItem := Item{
|
||||
Id: val,
|
||||
Text: val,
|
||||
Quantity: 1,
|
||||
Checked: false, //默认不选中
|
||||
}
|
||||
f.CachedList.Items = append(f.CachedList.Items, newItem)
|
||||
sort.Sort(f.CachedList)
|
||||
f.ItemList.Refresh()
|
||||
}
|
||||
|
||||
func (f *ItemList) 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.AddItemWithText(file.Name())
|
||||
// f.selItemIds = append(f.selItemIds, file.Name())
|
||||
f.ItemTotal++
|
||||
// logrus.Debugf("%v", file.Name())
|
||||
}
|
||||
}
|
||||
|
||||
f.SearchItem = f.CachedList.Items
|
||||
}
|
||||
|
||||
// 改变列表项目
|
||||
func (f *ItemList) ChangeItem(tmpDir, projectDir string) {
|
||||
f.ItemTotal = 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("没有任何变更的项目")
|
||||
}
|
||||
}()
|
||||
|
||||
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.AddItemWithText(file.Name())
|
||||
// f.SelItemIds = append(f.SelItemIds, file.Name())
|
||||
f.ItemTotal++
|
||||
// logrus.Debugf("%v", file.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 刷新文件数
|
||||
func (f *ItemList) ChangeFileCount() {
|
||||
f.TitleLabel.SetText(fmt.Sprintf("(%d/%d)", len(f.SelItemIds), f.ItemTotal))
|
||||
}
|
||||
|
||||
func (f *ItemList) 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.ItemTotal > 0 {
|
||||
f.ItemTotal--
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
190
cmd/v2/lib/common/lang.go
Normal file
190
cmd/v2/lib/common/lang.go
Normal file
@ -0,0 +1,190 @@
|
||||
package common
|
||||
|
||||
// en
|
||||
// const (
|
||||
// // app
|
||||
// APP_NAME = "protocol"
|
||||
|
||||
// app_testcase
|
||||
// APP_TESTCASE_INTRO = "select on left"
|
||||
// APP_TESTCASE_TITLE = "protocol test"
|
||||
// APP_TESTCASE_TITLE = "path"
|
||||
// APP_TESTCASE_BTN_CLEARLOG = "Clear Log"
|
||||
|
||||
//form
|
||||
// APP_TESTCASE_FORM_LABEL_HEROOBJID = "HeroObjID"
|
||||
// APP_TESTCASE_FORM_LABEL_RACECARD = "RaceObjID"
|
||||
// APP_TESTCASE_FORM_LABEL_CARD = "Hero"
|
||||
// APP_TESTCASE_FORM_LABEL_EXPCARDS = "ExpCardID"
|
||||
// APP_TESTCASE_FORM_LABEL_OID = "HeroObjOID"
|
||||
// APP_TESTCASE_FORM_LABEL_NUM = "Amount"
|
||||
// APP_TESTCASE_FORM_TASKTAG = "TaskTag"
|
||||
// APP_TESTCASE_FORM_TASK_OID = "TaskID"
|
||||
// APP_TESTCASE_FORM_NICKNAME = "NickName"
|
||||
// APP_TESTCASE_OPTIONS = "Option"
|
||||
// AAP_TESTCASE_FORM_TASK_DAY = "Day"
|
||||
// AAP_TESTCASE_FORM_TASK_WEEK = "Week"
|
||||
// AAP_TESTCASE_FORM_TASK_ACHIEVE = "Achieve"
|
||||
// // toolbar
|
||||
// TOOLBAR_WELCOME = "welcome"
|
||||
// TOOLBAR_TESTER = "tester"
|
||||
|
||||
// //button
|
||||
// BUTTON_LOGIN = "login"
|
||||
// BUTTON_REGISTE = "registe"
|
||||
// BUTTON_RANDOM = "random"
|
||||
// BUTTON_OK = "ok"
|
||||
// BUTTON_CANCEL = "cancel"
|
||||
|
||||
// //label
|
||||
// LABEL_CHOOSE = "welcome,The service you choose is "
|
||||
// LABEL_NICKNAME = "nickname"
|
||||
// LABEL_ACCOUNT = "account"
|
||||
// LABEL_WELCOME = "welcome "
|
||||
|
||||
// // form title
|
||||
// FORM_TITLE_CREATEROLE = "create role"
|
||||
// FORM_TITLE_LOGIN = "login"
|
||||
|
||||
// // info
|
||||
// INFO_WAIT = "Please wait"
|
||||
|
||||
// // menu
|
||||
// MENU_FILE = "file"
|
||||
|
||||
// //toy
|
||||
// // datetiem
|
||||
// DATETIME = "datetime"
|
||||
// //userinfo
|
||||
// USERINFO_TITLE = "用户信息"
|
||||
// USERINFO_UID = "UID"
|
||||
// USERINFO_ACC = "Acc"
|
||||
// USERINFO_NAME = "Name"
|
||||
// USERINFO_LV = "Lv"
|
||||
// USERINFO_GOLD = "Gold"
|
||||
// USERINFO_EXP = "Exp"
|
||||
// USERINFO_VIP = "VIP"
|
||||
// USERINFO_AVATAR = "Ava"
|
||||
// USERINFO_BTN_COPY = "COPY"
|
||||
// )
|
||||
|
||||
// zh
|
||||
const (
|
||||
APP_NAME = "机器人"
|
||||
|
||||
// app 子标题 [0.0.1 build-1] 应用名称
|
||||
APP_WIN_TITLE = "%s [%s build-%d] %s"
|
||||
WELCOME_MSG = "欢迎使用工具箱"
|
||||
|
||||
//about
|
||||
APP_ABOUT_TITLE = "关于"
|
||||
APP_ABOUT_CONFIRM = "好的"
|
||||
APP_ABOUT_INFO = `GUI 梦工厂工具`
|
||||
|
||||
// app_testcase
|
||||
APP_TESTCASE_TITLE = "接口测试"
|
||||
APP_TESTCASE_LABEL_PATH = "路径"
|
||||
APP_TESTCASE_BTN_CLEARLOG = "清除"
|
||||
APP_TESTCASE_INTRO = "选择左侧的测试接口"
|
||||
|
||||
// toolbar
|
||||
TOOLBAR_MONITOR = "推送"
|
||||
TOOLBAR_TESTER = "接口测试"
|
||||
TOOLBAR_GEN = "Luban"
|
||||
TOOLBAR_SEC = "密码器"
|
||||
TOOLBAR_WEL = "欢迎"
|
||||
TOOLBAR_TERM = "同步配置"
|
||||
TOOLBAR_PB = "protobuf"
|
||||
TOOLBAR_AUTO = "自动化"
|
||||
TOOLBAR_PING = "端口扫描"
|
||||
TOOLBAR_MGODB = "MongoDB"
|
||||
TOOLBAR_VALID = "配置校验"
|
||||
|
||||
TOOLBAR_PERF_TIP = "开始"
|
||||
TOOLBAR_PERF_CONF = "配置"
|
||||
TOOLBAR_PERF_LOGIN = "登陆"
|
||||
TOOLBAR_PERF_CREATE = "创角"
|
||||
TOOLBAR_PERF_CHOOSE = "选项"
|
||||
TOOLBAR_PERF_PB = "协议"
|
||||
TOOLBAR_PERF_RES = "结果"
|
||||
|
||||
//monitor
|
||||
APP_MONITOR_TITLE_ID = "编号"
|
||||
APP_MONITOR_TITLE_DATE = "时间"
|
||||
APP_MONITOR_TITLE_DATA = "数据"
|
||||
APP_MONITOR_BTN_VIEW = "查看"
|
||||
|
||||
//form
|
||||
APP_TESTCASE_FORM_LABEL_HEROOBJID = "卡片ID"
|
||||
APP_TESTCASE_FORM_LABEL_RACECARD = "种族卡片"
|
||||
APP_TESTCASE_FORM_LABEL_CARD = "卡片"
|
||||
APP_TESTCASE_FORM_LABEL_EXPCARDS = "经验卡"
|
||||
APP_TESTCASE_FORM_LABEL_OID = "卡片OID"
|
||||
APP_TESTCASE_FORM_LABEL_NUM = "数量"
|
||||
APP_TESTCASE_FORM_TASKTAG = "任务类型"
|
||||
APP_TESTCASE_FORM_TASK_OID = "任务OID"
|
||||
APP_TESTCASE_FORM_NICKNAME = "昵称"
|
||||
APP_TESTCASE_FORM_SIGN = "签名"
|
||||
APP_TESTCASE_OPTIONS = "选填"
|
||||
AAP_TESTCASE_FORM_TASK_DAY = "日常任务"
|
||||
APP_TESTCASE_FORM_TASK_WEEK = "周常任务"
|
||||
APP_TESTCASE_FORM_TASK_ACHIEVE = "成就"
|
||||
APP_TESTCASE_FORM_BINGO = "命令"
|
||||
APP_TESTCASE_BTN_PUSH = "推送"
|
||||
APP_TESTCASE_FORM_LABEL_FID = "好友ID"
|
||||
APP_TESTCASE_FORM_MAILID = "邮件ID"
|
||||
APP_TESTCASE_FORM_ITEMTYPE = "道具类型"
|
||||
APP_TESTCASE_FORM_ITEM_GEZIID = "格子ID"
|
||||
APP_TESTCASE_FORM_ITEM_GOODSID = "物品ID"
|
||||
APP_TESTCASE_FORM_ITEM_IDX = "下标"
|
||||
|
||||
//button
|
||||
BUTTON_LOGIN = "登录"
|
||||
BUTTON_REGISTE = "注册"
|
||||
BUTTON_RANDOM = "随机"
|
||||
BUTTON_OK = "确定"
|
||||
BUTTON_CANCEL = "取消"
|
||||
|
||||
//label
|
||||
LABEL_CHOOSE = "欢迎,你即将登录的服务是[%s]%s"
|
||||
LABEL_NICKNAME = "昵称"
|
||||
LABEL_ACCOUNT = "账号"
|
||||
LABEL_WELCOME = "欢迎 "
|
||||
|
||||
// form title
|
||||
FORM_TITLE_CREATEROLE = "创角"
|
||||
FORM_TITLE_LOGIN = "登录"
|
||||
|
||||
// info
|
||||
INFO_WAIT = "请稍后"
|
||||
|
||||
// menu
|
||||
MENU_FILE = "文件"
|
||||
|
||||
// toy
|
||||
// datetiem
|
||||
DATETIME = "时钟"
|
||||
|
||||
// userinfo
|
||||
USERINFO_BTN_COPY = "复制UID"
|
||||
USERINFO_BTN_REFRESH = "刷新"
|
||||
USERINFO_PANEL_TITLE = "用户信息"
|
||||
USERINFO_UID = "UID"
|
||||
USERINFO_SERVER = "区服"
|
||||
USERINFO_ACC = "账号"
|
||||
USERINFO_NAME = "昵称"
|
||||
USERINFO_TITLE = "头衔"
|
||||
USERINFO_LV = "等级"
|
||||
USERINFO_GOLD = "金币"
|
||||
USERINFO_EXP = "经验"
|
||||
USERINFO_DIAMOND = "钻石"
|
||||
USERINFO_VIP = "贵宾"
|
||||
USERINFO_AVATAR = "头像"
|
||||
USERINFO_FRIENDPOINT = "友情点"
|
||||
USERINFO_SIGN = "签名"
|
||||
USERINFO_MODINAME = "免费改名次数"
|
||||
USERINFO_ACTIVE_DAY = "日活"
|
||||
USERINFO_ACTIVE_WEEK = "周活"
|
||||
USERINFO_CREATETM = "创建"
|
||||
USERINFO_UPDATETM = "更新"
|
||||
)
|
75
cmd/v2/lib/common/list.go
Normal file
75
cmd/v2/lib/common/list.go
Normal file
@ -0,0 +1,75 @@
|
||||
package common
|
||||
|
||||
import "strings"
|
||||
|
||||
var replacer *strings.Replacer
|
||||
|
||||
func init() {
|
||||
trimChars := "0123456789-()/½⅓¼⅕⅙⅐⅛⅑⅔⅖¾⅗⅘"
|
||||
tcs := make([]string, len(trimChars)*2)
|
||||
for i, c := range trimChars {
|
||||
tcs[i*2] = string(c)
|
||||
tcs[i*2+1] = ""
|
||||
}
|
||||
replacer = strings.NewReplacer(tcs...)
|
||||
}
|
||||
|
||||
type List struct {
|
||||
Name string `json:"name"`
|
||||
Group string `json:"group"`
|
||||
Items []Item `json:"items"`
|
||||
// ID is the Mealie API reference for the list.
|
||||
ID int `json:"id"`
|
||||
}
|
||||
|
||||
var sortableText map[string]string = map[string]string{}
|
||||
|
||||
func (l List) Len() int { return len(l.Items) }
|
||||
func (l List) Swap(i, j int) { l.Items[i], l.Items[j] = l.Items[j], l.Items[i] }
|
||||
|
||||
func (l List) Less(i, j int) bool {
|
||||
var ok bool
|
||||
var it, jt string
|
||||
li := l.Items[i]
|
||||
lit := li.Text
|
||||
if it, ok = sortableText[lit]; !ok {
|
||||
it = replacer.Replace(strings.ToUpper(lit))
|
||||
it = strings.TrimLeft(it, " ")
|
||||
sortableText[lit] = it
|
||||
}
|
||||
lj := l.Items[j]
|
||||
ljt := lj.Text
|
||||
if jt, ok = sortableText[ljt]; !ok {
|
||||
jt = replacer.Replace(strings.ToUpper(ljt))
|
||||
jt = strings.TrimLeft(jt, " ")
|
||||
sortableText[ljt] = jt
|
||||
}
|
||||
if !li.Checked {
|
||||
if lj.Checked {
|
||||
return true
|
||||
}
|
||||
return it < jt
|
||||
}
|
||||
if !lj.Checked {
|
||||
return false
|
||||
}
|
||||
return it < jt
|
||||
}
|
||||
|
||||
type Item struct {
|
||||
Id string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Text string `json:"text"`
|
||||
Quantity int `json:"quantity"`
|
||||
Checked bool `json:"checked"`
|
||||
Size int64 `json:"size"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
func NewList(name string) List {
|
||||
return List{
|
||||
ID: -1,
|
||||
Name: name,
|
||||
Items: []Item{},
|
||||
}
|
||||
}
|
10
cmd/v2/lib/common/log.go
Normal file
10
cmd/v2/lib/common/log.go
Normal file
@ -0,0 +1,10 @@
|
||||
package common
|
||||
|
||||
type LogData struct {
|
||||
Level string `json:"level"`
|
||||
MainType string `json:"mainType"`
|
||||
SubType string `json:"subType"`
|
||||
Time string `json:"time"`
|
||||
Msg string `json:"msg"`
|
||||
Params interface{} `json:"params"`
|
||||
}
|
57
cmd/v2/lib/common/mongo.go
Normal file
57
cmd/v2/lib/common/mongo.go
Normal file
@ -0,0 +1,57 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
os_storage "go_dreamfactory/cmd/v2/lib/storage"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type MogoTool struct {
|
||||
conf *os_storage.Config
|
||||
storage os_storage.Storage
|
||||
db *mongo.Database
|
||||
client *mongo.Client
|
||||
}
|
||||
|
||||
func NewMogoTool() *MogoTool {
|
||||
this := &MogoTool{}
|
||||
this.storage, _ = os_storage.NewOSStorage()
|
||||
var err error
|
||||
this.conf, err = this.storage.LoadConfig()
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
func (this *MogoTool) OpenConn() {
|
||||
if this.conf.MgoDB == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var option *options.ClientOptions
|
||||
if (this.conf.MgoDB.User == "" && this.conf.MgoDB.Password == "") &&
|
||||
this.conf.MgoDB.Host != "" && this.conf.MgoDB.Port != 0 && this.conf.MgoDB.Database != "" {
|
||||
option = options.Client().ApplyURI(fmt.Sprintf("mongodb://%s:%d", this.conf.MgoDB.Host, this.conf.MgoDB.Port))
|
||||
} else {
|
||||
option = options.Client().ApplyURI(fmt.Sprintf("mongodb://%s:%s@%s:%d", this.conf.MgoDB.User, this.conf.MgoDB.Password,
|
||||
this.conf.MgoDB.Host, this.conf.MgoDB.Port))
|
||||
}
|
||||
client, err := mongo.Connect(context.TODO(), option)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
if err2 := client.Ping(context.TODO(), nil); err2 != nil {
|
||||
logrus.Error("Mongo连接失败", err2)
|
||||
return
|
||||
}
|
||||
this.db = client.Database(this.conf.MgoDB.Database)
|
||||
logrus.Info("mongo connect successful")
|
||||
}
|
25
cmd/v2/lib/common/sec.go
Normal file
25
cmd/v2/lib/common/sec.go
Normal file
@ -0,0 +1,25 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go_dreamfactory/cmd/v2/model"
|
||||
"go_dreamfactory/utils"
|
||||
"time"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/nacos-group/nacos-sdk-go/util"
|
||||
)
|
||||
|
||||
func BuildSecStr(sid, account string) string {
|
||||
now := time.Now().Unix()
|
||||
jsonByte, _ := jsoniter.Marshal(&model.LoginParam{
|
||||
Account: account,
|
||||
ServerId: sid,
|
||||
TimeStamp: now,
|
||||
})
|
||||
jsonBase64 := utils.Base64Encode(jsonByte)
|
||||
// log.Printf("client base64:%s", jsonBase64)
|
||||
clientMd5key := util.Md5(jsonBase64)
|
||||
// logrus.Debugf("client md5:%s", clientMd5key)
|
||||
return fmt.Sprintf("CE:%s%s", clientMd5key, jsonBase64)
|
||||
}
|
40
cmd/v2/lib/common/tip.go
Normal file
40
cmd/v2/lib/common/tip.go
Normal file
@ -0,0 +1,40 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"time"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/driver/desktop"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
// 显示Tip
|
||||
func ShowTip(content string) {
|
||||
drv := fyne.CurrentApp().Driver()
|
||||
if drv, ok := drv.(desktop.Driver); ok {
|
||||
w := drv.CreateSplashWindow()
|
||||
w.SetContent(widget.NewLabelWithStyle(content, fyne.TextAlignCenter, fyne.TextStyle{}))
|
||||
w.Show()
|
||||
|
||||
go func() {
|
||||
time.Sleep(time.Millisecond * 1500)
|
||||
w.Close()
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func ShowCanvasTip(content string) {
|
||||
drv := fyne.CurrentApp().Driver()
|
||||
if drv, ok := drv.(desktop.Driver); ok {
|
||||
w := drv.CreateSplashWindow()
|
||||
w.SetContent(canvas.NewText(content, color.RGBA{255, 0, 0, 255}))
|
||||
w.Show()
|
||||
|
||||
go func() {
|
||||
time.Sleep(time.Millisecond * 1500)
|
||||
w.Close()
|
||||
}()
|
||||
}
|
||||
}
|
261
cmd/v2/lib/common/utils.go
Normal file
261
cmd/v2/lib/common/utils.go
Normal file
@ -0,0 +1,261 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go_dreamfactory/lego/core"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cast"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func MF(s1 core.M_Modules, s2 string) string {
|
||||
return fmt.Sprintf("%s.%s", s1, s2)
|
||||
}
|
||||
|
||||
func FormatJson(data string) (string, error) {
|
||||
var out bytes.Buffer
|
||||
err := json.Indent(&out, []byte(data), "", " ")
|
||||
return out.String(), err
|
||||
}
|
||||
|
||||
func SubStr(str string, start int, length int) (result string) {
|
||||
s := []rune(str)
|
||||
total := len(s)
|
||||
if total == 0 {
|
||||
return
|
||||
}
|
||||
// 允许从尾部开始计算
|
||||
if start < 0 {
|
||||
start = total + start
|
||||
if start < 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
if start > total {
|
||||
return
|
||||
}
|
||||
// 到末尾
|
||||
if length < 0 {
|
||||
length = total
|
||||
}
|
||||
|
||||
end := start + length
|
||||
if end > total {
|
||||
result = string(s[start:])
|
||||
} else {
|
||||
result = string(s[start:end])
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 是否升级
|
||||
func IsUpgrade(newVersion, oldVersion string) bool {
|
||||
nvArr := strings.SplitN(newVersion, ".", 3)
|
||||
if len(nvArr) != 3 {
|
||||
logrus.Error("new version format err")
|
||||
return false
|
||||
}
|
||||
|
||||
ovArr := strings.SplitN(oldVersion, ".", 3)
|
||||
if len(ovArr) != 3 {
|
||||
logrus.Error("old version format err")
|
||||
return false
|
||||
}
|
||||
|
||||
nvNum := cast.ToInt(nvArr[0])*100 + cast.ToInt(nvArr[1])*10 + cast.ToInt(nvArr[2])
|
||||
ovNum := cast.ToInt(ovArr[0])*100 + cast.ToInt(ovArr[1])*10 + cast.ToInt(ovArr[2])
|
||||
|
||||
if nvNum > ovNum {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func Copy(src, dst string) (len int64, err error) {
|
||||
|
||||
dstWriter, err := os.Create(dst)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
srcReader, err := os.Open(src)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
// Copy()函数其实是调用了
|
||||
// io包中私有函数copyBuffer() 默认缓冲区是32K
|
||||
// 与Copy()函数功能一致的是CopyBuffer()可以设置缓冲区
|
||||
len, err = io.Copy(dstWriter, srcReader)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteFile(filePath string) error {
|
||||
return os.Remove(filePath)
|
||||
}
|
||||
|
||||
func RemoveContents(dir string) error {
|
||||
d, err := os.Open(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer d.Close()
|
||||
names, err := d.Readdirnames(-1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, name := range names {
|
||||
err = os.RemoveAll(filepath.Join(dir, name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ConvertFileSize(size int64) string {
|
||||
if size == 0 {
|
||||
return "0"
|
||||
}
|
||||
|
||||
kb := float64(size) / float64(1024)
|
||||
|
||||
if kb < 1024 {
|
||||
f := math.Ceil(kb)
|
||||
return strconv.Itoa(int(f)) + " KB"
|
||||
}
|
||||
|
||||
mb := kb / float64(1024)
|
||||
if mb < 1024 {
|
||||
f := math.Ceil(mb)
|
||||
return strconv.Itoa(int(f)) + " MB"
|
||||
}
|
||||
|
||||
gb := mb / float64(1024)
|
||||
if gb < 1024 {
|
||||
f := math.Ceil(mb)
|
||||
return strconv.Itoa(int(f)) + " G"
|
||||
}
|
||||
|
||||
t := gb / float64(1024)
|
||||
if t < 1024 {
|
||||
f := math.Ceil(mb)
|
||||
return strconv.Itoa(int(f)) + " T"
|
||||
}
|
||||
|
||||
if t >= 1024 {
|
||||
return "VeryBig"
|
||||
}
|
||||
|
||||
return "0"
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
func (this *Config) SetPath(path string) {
|
||||
this.Path = path
|
||||
}
|
||||
|
||||
// "F:\\projects\\workspace\\go_dreamfactory\\bin\\json"
|
||||
func (this *Config) Loader(file string) ([]map[string]interface{}, error) {
|
||||
if this.Path == "" {
|
||||
return nil, errors.New("no setting config path")
|
||||
}
|
||||
path := filepath.Join(this.Path, file+".json")
|
||||
if bytes, err := ioutil.ReadFile(path); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
jsonData := make([]map[string]interface{}, 0)
|
||||
if err = json.Unmarshal(bytes, &jsonData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return jsonData, nil
|
||||
}
|
||||
}
|
||||
|
||||
func Json2Pb(jsonString string, pb proto.Message) error {
|
||||
m := pb.ProtoReflect().Interface()
|
||||
if err := protojson.Unmarshal([]byte(jsonString), m); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Pb2Json(pb proto.Message) string {
|
||||
return protojson.Format(pb.ProtoReflect().Interface())
|
||||
}
|
||||
|
||||
// 保留两位小数 通用
|
||||
func FormatFloatCommon(num float64) float64 {
|
||||
value, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", num), 64)
|
||||
return value
|
||||
}
|
||||
|
||||
// 保留两位小数,舍弃尾数,无进位运算
|
||||
// 主要逻辑就是先乘,trunc之后再除回去,就达到了保留N位小数的效果
|
||||
func FormatFloat(num float64, decimal int) (float64, error) {
|
||||
// 默认乘1
|
||||
d := float64(1)
|
||||
if decimal > 0 {
|
||||
// 10的N次方
|
||||
d = math.Pow10(decimal)
|
||||
}
|
||||
// math.trunc作用就是返回浮点数的整数部分
|
||||
// 再除回去,小数点后无效的0也就不存在了
|
||||
res := strconv.FormatFloat(math.Trunc(num*d)/d, 'f', -1, 64)
|
||||
return strconv.ParseFloat(res, 64)
|
||||
}
|
||||
|
||||
// 强制舍弃尾数
|
||||
func FormatFloatFloor(num float64, decimal int) (float64, error) {
|
||||
// 默认乘1
|
||||
d := float64(1)
|
||||
if decimal > 0 {
|
||||
// 10的N次方
|
||||
d = math.Pow10(decimal)
|
||||
}
|
||||
// math.trunc作用就是返回浮点数的整数部分
|
||||
// 再除回去,小数点后无效的0也就不存在了
|
||||
res := strconv.FormatFloat(math.Floor(num*d)/d, 'f', -1, 64)
|
||||
return strconv.ParseFloat(res, 64)
|
||||
}
|
||||
|
||||
// 舍弃的尾数不为0,强制进位
|
||||
func FormatFloatCeil(num float64, decimal int) (float64, error) {
|
||||
// 默认乘1
|
||||
d := float64(1)
|
||||
if decimal > 0 {
|
||||
// 10的N次方
|
||||
d = math.Pow10(decimal)
|
||||
}
|
||||
// math.trunc作用就是返回浮点数的整数部分
|
||||
// 再除回去,小数点后无效的0也就不存在了
|
||||
res := strconv.FormatFloat(math.Ceil(num*d)/d, 'f', -1, 64)
|
||||
return strconv.ParseFloat(res, 64)
|
||||
}
|
||||
|
||||
func LastChars(str string, count int) string {
|
||||
if len(str) <= count {
|
||||
return str
|
||||
}
|
||||
return str[len(str)-count:]
|
||||
}
|
65
cmd/v2/lib/common/utils_test.go
Normal file
65
cmd/v2/lib/common/utils_test.go
Normal file
@ -0,0 +1,65 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go_dreamfactory/pb"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSubStr(t *testing.T) {
|
||||
str := "type.googleapis.com/UserResChangePush"
|
||||
r := SubStr(str, 20, len(str))
|
||||
fmt.Println(r)
|
||||
}
|
||||
|
||||
func TestConver(t *testing.T) {
|
||||
|
||||
s := ConvertFileSize(25325466)
|
||||
fmt.Println(s)
|
||||
}
|
||||
|
||||
func TestIsUpgrade(t *testing.T) {
|
||||
IsUpgrade("1.2.2", "1.0.21")
|
||||
}
|
||||
|
||||
func TestJsonToPb(t *testing.T) {
|
||||
jsonStr := `{"account":"zhaocy","sid":"dfz"}`
|
||||
login := &pb.UserLoginReq{}
|
||||
Json2Pb(jsonStr, login)
|
||||
fmt.Println(login.Account, login.Sid)
|
||||
|
||||
fmt.Println(Pb2Json(login))
|
||||
|
||||
t2 := reflect.TypeOf(login)
|
||||
fmt.Println("Name:", t2.Elem().Name())
|
||||
}
|
||||
|
||||
func TestSpli(t *testing.T) {
|
||||
now := time.Now()
|
||||
fmt.Println(now.UnixNano())
|
||||
fmt.Println(now.UnixNano() / 1e6) //将纳秒转换为毫秒
|
||||
}
|
||||
|
||||
func TestDiv(t *testing.T) {
|
||||
numF := float64(32766600)
|
||||
// 保留两位小数, 通用
|
||||
value, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", numF/1e6), 64)
|
||||
fmt.Println(reflect.TypeOf(value), value)
|
||||
fmt.Println(FormatFloatCommon(numF / 1e6))
|
||||
|
||||
num, _ := FormatFloat(numF, 2)
|
||||
fmt.Println(reflect.TypeOf(num), num)
|
||||
// 舍弃的尾数不为0,强制进位
|
||||
num, _ = FormatFloatCeil(0.2205, 2)
|
||||
fmt.Println(reflect.TypeOf(num), num)
|
||||
// 强制舍弃尾数
|
||||
num, _ = FormatFloatFloor(0.2295, 2)
|
||||
fmt.Println(reflect.TypeOf(num), num)
|
||||
}
|
||||
|
||||
func TestSub(t *testing.T){
|
||||
fmt.Println(LastChars("23af2", 6))
|
||||
}
|
7
cmd/v2/lib/core.go
Normal file
7
cmd/v2/lib/core.go
Normal file
@ -0,0 +1,7 @@
|
||||
package lib
|
||||
|
||||
type Aiassistant interface {
|
||||
Start() bool
|
||||
Stop() error
|
||||
ShowResult()
|
||||
}
|
60
cmd/v2/lib/gopool.go
Normal file
60
cmd/v2/lib/gopool.go
Normal file
@ -0,0 +1,60 @@
|
||||
package lib
|
||||
|
||||
import "errors"
|
||||
|
||||
type GoPool interface {
|
||||
Take()
|
||||
Return()
|
||||
Total() uint32
|
||||
Remainder() uint32
|
||||
}
|
||||
|
||||
var _ GoPool = (*myGoPool)(nil)
|
||||
|
||||
type myGoPool struct {
|
||||
total uint32 //总数
|
||||
poolCh chan struct{} //池子容量
|
||||
active bool //是否激活
|
||||
}
|
||||
|
||||
func NewGoPool(total uint32) (GoPool, error) {
|
||||
gp := myGoPool{}
|
||||
if !gp.init(total) {
|
||||
return nil, errors.New("携程池初始化失败")
|
||||
}
|
||||
return &gp, nil
|
||||
}
|
||||
|
||||
func (gp *myGoPool) init(total uint32) bool {
|
||||
if gp.active {
|
||||
return false
|
||||
}
|
||||
if total == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
ch := make(chan struct{}, total)
|
||||
n := int(total)
|
||||
for i := 0; i < n; i++ {
|
||||
ch <- struct{}{}
|
||||
}
|
||||
|
||||
gp.poolCh = ch
|
||||
gp.total = total
|
||||
gp.active = true
|
||||
return true
|
||||
}
|
||||
|
||||
func (gp *myGoPool) Take() {
|
||||
<-gp.poolCh
|
||||
}
|
||||
|
||||
func (gp *myGoPool) Return() {
|
||||
gp.poolCh <- struct{}{}
|
||||
}
|
||||
|
||||
func (gp *myGoPool) Total() uint32 { return gp.total }
|
||||
|
||||
func (gp *myGoPool) Remainder() uint32 {
|
||||
return uint32(len(gp.poolCh))
|
||||
}
|
38
cmd/v2/lib/handler.go
Normal file
38
cmd/v2/lib/handler.go
Normal file
@ -0,0 +1,38 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 处理器接口
|
||||
type Handler interface {
|
||||
SetReq(req []byte, flag bool)
|
||||
// 处理请求
|
||||
BuildReq() RawReq
|
||||
//调用
|
||||
Call(req []byte) ([]byte, error)
|
||||
// 检查响应
|
||||
Check(req RawReq, rsp RawResp) *CallResult
|
||||
|
||||
GetConnMap() sync.Map
|
||||
}
|
||||
|
||||
// 调用结果
|
||||
type CallResult struct {
|
||||
Id int64
|
||||
Req RawReq
|
||||
Resp RawResp
|
||||
Code ResCode
|
||||
Message string
|
||||
Elapse time.Duration
|
||||
}
|
||||
|
||||
type Statistics struct {
|
||||
ElapseTotal float64 //总耗时
|
||||
MaxElapse float64 //最大耗时
|
||||
MinElapse float64 //最小耗时
|
||||
AvgElapse float64 //平均耗时
|
||||
CallCount int64 //调用次数
|
||||
Route string //协议名称
|
||||
}
|
57
cmd/v2/lib/param.go
Normal file
57
cmd/v2/lib/param.go
Normal file
@ -0,0 +1,57 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ParamMgr struct {
|
||||
Timeout time.Duration
|
||||
Lps uint32
|
||||
Duration time.Duration
|
||||
Caller Handler //调用器
|
||||
ResultCh chan *CallResult //调用结果
|
||||
}
|
||||
|
||||
func (param *ParamMgr) Check() error {
|
||||
var errMsgs []string
|
||||
|
||||
if param.Caller == nil {
|
||||
errMsgs = append(errMsgs, "无效的调用器")
|
||||
}
|
||||
|
||||
if param.Timeout == 0 {
|
||||
errMsgs = append(errMsgs, "参数Timeout无效")
|
||||
}
|
||||
|
||||
if param.Duration == 0 {
|
||||
errMsgs = append(errMsgs, "参数Duration无效")
|
||||
}
|
||||
|
||||
if param.Lps == 0 {
|
||||
errMsgs = append(errMsgs, "参数lps无效")
|
||||
}
|
||||
|
||||
if param.ResultCh == nil {
|
||||
errMsgs = append(errMsgs, "结果通过未实例化")
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString("校验参数")
|
||||
if errMsgs != nil {
|
||||
errMsg := strings.Join(errMsgs, " ")
|
||||
buf.WriteString(fmt.Sprintf("没有通过 %s", errMsg))
|
||||
logrus.Infoln(buf.String())
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
|
||||
buf.WriteString(fmt.Sprintf("通过. (timeoutMS=%s, lps=%d, durationS=%s)",
|
||||
param.Timeout, param.Lps, param.Duration))
|
||||
logrus.Debugln(buf.String())
|
||||
return nil
|
||||
}
|
867
cmd/v2/lib/pb/protocol.go
Normal file
867
cmd/v2/lib/pb/protocol.go
Normal file
@ -0,0 +1,867 @@
|
||||
package pb
|
||||
|
||||
import (
|
||||
// "errors"
|
||||
// "fmt"
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/cmd/v2/model"
|
||||
"go_dreamfactory/pb"
|
||||
// "go_dreamfactory/comm"
|
||||
// "go_dreamfactory/modules/friend"
|
||||
// "go_dreamfactory/modules/growtask"
|
||||
// "go_dreamfactory/modules/hero"
|
||||
// "go_dreamfactory/modules/library"
|
||||
// "go_dreamfactory/modules/linestory"
|
||||
// "go_dreamfactory/modules/mline"
|
||||
// "go_dreamfactory/modules/sociaty"
|
||||
// "go_dreamfactory/modules/sys"
|
||||
// "go_dreamfactory/modules/task"
|
||||
// "go_dreamfactory/modules/user"
|
||||
// "go_dreamfactory/modules/worldtask"
|
||||
// "go_dreamfactory/pb"
|
||||
// "strings"
|
||||
// "github.com/sirupsen/logrus"
|
||||
// "google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// 2 添加导航菜单
|
||||
var (
|
||||
CaseIndex = map[string][]string{
|
||||
"": {
|
||||
string("gm"),
|
||||
// string(comm.ModuleSys),
|
||||
// string(comm.ModuleUser),
|
||||
// string(comm.ModuleHero),
|
||||
// string(comm.ModuleTask),
|
||||
// string(comm.ModuleFriend),
|
||||
// string(comm.ModuleMail),
|
||||
// string(comm.ModuleItems),
|
||||
// string(comm.ModuleEquipment),
|
||||
// string(comm.ModuleShop),
|
||||
// string(comm.ModuleMline),
|
||||
// string(comm.ModulePagoda),
|
||||
// string(comm.ModuleRtask),
|
||||
// string(comm.ModuleLinestory),
|
||||
// string(comm.ModuleGourmet),
|
||||
// string(comm.ModuleSociaty),
|
||||
// string(comm.ModuleTroll),
|
||||
// string(comm.ModuleGrowtask),
|
||||
string("worldtask"),
|
||||
// string(comm.ModuleReddot),
|
||||
string("smithy"),
|
||||
// string(comm.ModuleDispatch),
|
||||
// string(comm.ModuleReputation),
|
||||
// string(comm.ModuleOldtimes),
|
||||
},
|
||||
"gm": {
|
||||
common.MF("gm", "cmd"),
|
||||
// common.MF(comm.ModuleGM, "gi"),
|
||||
},
|
||||
"sys": {
|
||||
// common.MF(comm.ModuleSys, "funclist"),
|
||||
},
|
||||
// "reddot": {common.MF(comm.ModuleReddot, "get")},
|
||||
"user": {
|
||||
// common.MF(comm.ModuleUser, user.UserSubTypeModifyAvatar),
|
||||
// common.MF(comm.ModuleUser, user.UserSubTypeModifyName),
|
||||
// common.MF(comm.ModuleUser, user.UserSubTypeModifyFigure),
|
||||
// common.MF(comm.ModuleUser, user.UserSubTYpeModifyBgp),
|
||||
// common.MF(comm.ModuleUser, user.UserSubTypeModifySign),
|
||||
// common.MF(comm.ModuleUser, user.UserSubTypeBattlerecord),
|
||||
},
|
||||
"items": {
|
||||
// common.MF(comm.ModuleItems, "getlist"),
|
||||
// common.MF(comm.ModuleItems, "sellitem"),
|
||||
// common.MF(comm.ModuleItems, "useitem"),
|
||||
},
|
||||
"mail": {
|
||||
// common.MF(comm.ModuleMail, "getlist"),
|
||||
// common.MF(comm.ModuleMail, "readmail"),
|
||||
// common.MF(comm.ModuleMail, "delmail"),
|
||||
// common.MF(comm.ModuleMail, "getusermailattachment"),
|
||||
// common.MF(comm.ModuleMail, "getallmailattachment"),
|
||||
},
|
||||
"hero": {
|
||||
// common.MF(comm.ModuleHero, hero.HeroSubTypeList),
|
||||
// common.MF(comm.ModuleHero, hero.StrengthenUplv),
|
||||
// common.MF(comm.ModuleHero, hero.StrengthenUpStar),
|
||||
// common.MF(comm.ModuleHero, hero.DrawCard),
|
||||
// common.MF(comm.ModuleHero, "info"),
|
||||
},
|
||||
"equipment": {
|
||||
// common.MF(comm.ModuleEquipment, "getlist"),
|
||||
// common.MF(comm.ModuleEquipment, "equip"),
|
||||
// common.MF(comm.ModuleEquipment, "upgrade"),
|
||||
},
|
||||
"task": {
|
||||
// common.MF(comm.ModuleTask, task.TaskSubTypeList),
|
||||
// common.MF(comm.ModuleTask, task.TaskSubTypeActiveList),
|
||||
// common.MF(comm.ModuleTask, task.TaskSubTypeActiveReceive),
|
||||
// common.MF(comm.ModuleTask, task.TaskSubTypeGetrecord),
|
||||
},
|
||||
"friend": {
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeList),
|
||||
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeAgree),
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeBlacklist),
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeAddBlack),
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeDelBlack),
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeRandList),
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeGetreward),
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeAssistHero),
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeAssistlist),
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeAssistHeroList),
|
||||
},
|
||||
"shop": {
|
||||
// common.MF(comm.ModuleShop, "getlist"),
|
||||
// common.MF(comm.ModuleShop, "buy"),
|
||||
},
|
||||
"mainline": {
|
||||
// common.MF(comm.ModuleMline, mline.MlineGetListResp),
|
||||
// common.MF(comm.ModuleMline, mline.MlineChallengeResp),
|
||||
// common.MF(comm.ModuleMline, mline.MlineGetRewardResp),
|
||||
},
|
||||
"pagoda": {
|
||||
// common.MF(comm.ModulePagoda, "getlist"),
|
||||
},
|
||||
"linestory": {
|
||||
// common.MF(comm.ModuleLinestory, linestory.LinestorySubTypeChapter),
|
||||
// common.MF(comm.ModuleLibrary, library.LibraryFetterstoryTaskResp),
|
||||
},
|
||||
"gourmet": {
|
||||
// common.MF(comm.ModuleGourmet, "getranduser"),
|
||||
},
|
||||
"sociaty": {
|
||||
// common.MF(comm.ModuleSociaty, sociaty.SociatySubTypeList),
|
||||
// common.MF(comm.ModuleSociaty, sociaty.SociatySubTypeCreate),
|
||||
// common.MF(comm.ModuleSociaty, sociaty.SociatySubTypeMine),
|
||||
// common.MF(comm.ModuleSociaty, sociaty.SociatySubTypeTasklist),
|
||||
// common.MF(comm.ModuleSociaty, sociaty.SociatySubTypeRank),
|
||||
// common.MF(comm.ModuleSociaty, "boss"),
|
||||
},
|
||||
"troll": {
|
||||
// common.MF(comm.ModuleTroll, "getlist"),
|
||||
},
|
||||
"growtask": {
|
||||
// common.MF(comm.ModuleGrowtask, growtask.GrowtaskSubTypeList),
|
||||
},
|
||||
"worldtask": {
|
||||
// common.MF(comm.ModuleWorldtask, worldtask.WorldtaskSubtypeMine),
|
||||
// common.MF(comm.ModuleWorldtask, "check"),
|
||||
common.MF("worldtask", "test"),
|
||||
},
|
||||
"smithy": {
|
||||
common.MF("smithy", "tasklist"),
|
||||
},
|
||||
"dispatch": {
|
||||
// common.MF(comm.ModuleDispatch, "dispatch"),
|
||||
// common.MF(comm.ModulePractice, "practice"),
|
||||
},
|
||||
"reputation": {
|
||||
// common.MF(comm.ModuleReputation, "reputation"),
|
||||
},
|
||||
"oldtimes": {
|
||||
// common.MF(comm.ModuleOldtimes, "oldtimes"),
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// 3 注册测试用例
|
||||
var (
|
||||
CaseNav = map[string]*model.TestCase{
|
||||
// gm
|
||||
"gm": {
|
||||
NavLabel: "GM",
|
||||
MainType: string("gm"),
|
||||
Enabled: true,
|
||||
},
|
||||
common.MF("gm", "cmd"): {
|
||||
Desc: "eg. bingo:item,10001,1 bingo:attr,gold,1000000",
|
||||
MainType: string("gm"),
|
||||
SubType: "cmd",
|
||||
Req: &pb.GMCmdReq{},
|
||||
Rsp: &pb.GMCmdResp{},
|
||||
Enabled: true,
|
||||
},
|
||||
// common.MF(comm.ModuleGM, "gi"): {
|
||||
// NavLabel: "实例配置",
|
||||
// Desc: "全局实例配置",
|
||||
// MainType: string(comm.ModuleGM),
|
||||
// SubType: "gi",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// "reddot": {
|
||||
// NavLabel: "红点",
|
||||
// MainType: string(comm.ModuleReddot),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleReddot, "get"): {
|
||||
// Desc: "红点",
|
||||
// NavLabel: "红点",
|
||||
// MainType: string(comm.ModuleReddot),
|
||||
// SubType: "get",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// "sys": {
|
||||
// NavLabel: "系统",
|
||||
// MainType: string(comm.ModuleSys),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleSys, "funclist"): {
|
||||
// NavLabel: "功能列表",
|
||||
// Desc: "返回未开启的功能列表",
|
||||
// MainType: string(comm.ModuleSys),
|
||||
// // SubType: sys.SysSubTypeFunc,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// // user
|
||||
// "user": {
|
||||
// NavLabel: "用户",
|
||||
// MainType: "user",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleUser, user.UserSubTypeModifyAvatar): {
|
||||
// Desc: "用户头像修改",
|
||||
// NavLabel: "修改头像",
|
||||
// MainType: string(comm.ModuleUser),
|
||||
// SubType: user.UserSubTypeModifyAvatar,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// "user.modifyname": {
|
||||
// Desc: "用户昵称修改",
|
||||
// NavLabel: "修改昵称",
|
||||
// MainType: "user",
|
||||
// SubType: "modifyname",
|
||||
// Req: &pb.UserModifynameReq{},
|
||||
// Rsp: &pb.UserModifynameResp{},
|
||||
// Print: func(rsp proto.Message) string {
|
||||
// logrus.WithFields(logrus.Fields{"main": "user", "stype": "modifyname"}).Debug("print")
|
||||
// var formatStr strings.Builder
|
||||
|
||||
// if in, ok := rsp.(*pb.UserMessage); ok {
|
||||
// out := &pb.UserModifynameResp{}
|
||||
// if !comm.ProtoUnmarshal(in, out) {
|
||||
// return errors.New("unmarshal err").Error()
|
||||
// }
|
||||
// formatStr.WriteString(fmt.Sprintf("Uid:%s count:%d", out.Uid, out.Count))
|
||||
// }
|
||||
// return formatStr.String()
|
||||
// },
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleUser, user.UserSubTypeModifyFigure): {
|
||||
// Desc: "用户形象修改",
|
||||
// NavLabel: "修改形象",
|
||||
// MainType: string(comm.ModuleUser),
|
||||
// SubType: user.UserSubTypeModifyFigure,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleUser, user.UserSubTYpeModifyBgp): {
|
||||
// Desc: "背景修改",
|
||||
// NavLabel: "修改背景",
|
||||
// MainType: string(comm.ModuleUser),
|
||||
// SubType: user.UserSubTYpeModifyBgp,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleUser, user.UserSubTypeModifySign): {
|
||||
// NavLabel: "修改签名",
|
||||
// Desc: "用户签名修改",
|
||||
// MainType: string(comm.ModuleUser),
|
||||
// SubType: user.UserSubTypeModifySign,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleUser, user.UserSubTypeBattlerecord): {
|
||||
// NavLabel: "战斗记录",
|
||||
// Desc: "玩家在心魔塔、狩猎、维京远征的战斗记录",
|
||||
// MainType: string(comm.ModuleUser),
|
||||
// SubType: user.UserSubTypeBattlerecord,
|
||||
// Enabled: true,
|
||||
// },
|
||||
//items
|
||||
// string(comm.ModuleItems): {
|
||||
// NavLabel: "道具",
|
||||
// MainType: string(comm.ModuleItems),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleItems, "getlist"): {
|
||||
// NavLabel: "道具列表",
|
||||
// Desc: "道具列表",
|
||||
// MainType: string(comm.ModuleItems),
|
||||
// SubType: "getlist",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleItems, "sellitem"): {
|
||||
// NavLabel: "道具售卖",
|
||||
// Desc: "道具售卖",
|
||||
// MainType: string(comm.ModuleItems),
|
||||
// SubType: "sellitem",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleItems, "useitem"): {
|
||||
// NavLabel: "道具使用",
|
||||
// Desc: "道具使用",
|
||||
// MainType: string(comm.ModuleItems),
|
||||
// SubType: "useitem",
|
||||
// Enabled: true,
|
||||
// },
|
||||
|
||||
//mail
|
||||
// string(comm.ModuleMail): {
|
||||
// NavLabel: "邮箱",
|
||||
// MainType: string(comm.ModuleMail),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleMail, "getlist"): {
|
||||
// NavLabel: "我的邮件",
|
||||
// Desc: "我的邮件",
|
||||
// MainType: string(comm.ModuleMail),
|
||||
// SubType: "getlist",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleMail, "readmail"): {
|
||||
// NavLabel: "读邮件",
|
||||
// Desc: "读取邮件",
|
||||
// MainType: string(comm.ModuleMail),
|
||||
// SubType: "readmail",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleMail, "delmail"): {
|
||||
// NavLabel: "删除邮件",
|
||||
// Desc: "删除邮件",
|
||||
// MainType: string(comm.ModuleMail),
|
||||
// SubType: "delmail",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleMail, "getusermailattachment"): {
|
||||
// NavLabel: "领取附件",
|
||||
// Desc: "领取附件",
|
||||
// MainType: string(comm.ModuleMail),
|
||||
// SubType: "getusermailattachment",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleMail, "getallmailattachment"): {
|
||||
// NavLabel: "一键领取",
|
||||
// Desc: "领取所有附件",
|
||||
// MainType: string(comm.ModuleMail),
|
||||
// SubType: "getallmailattachment",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// task
|
||||
// "task": {
|
||||
// NavLabel: "任务",
|
||||
// MainType: "task",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// "task.list": {
|
||||
// NavLabel: "任务列表",
|
||||
// Desc: "用户任务列表",
|
||||
// MainType: "task",
|
||||
// SubType: "list",
|
||||
// Req: &pb.TaskListReq{},
|
||||
// Rsp: &pb.TaskListResp{},
|
||||
// Enabled: true,
|
||||
// Print: func(rsp proto.Message) string {
|
||||
// logrus.WithFields(logrus.Fields{"main": "task", "stype": "list"}).Debug("print")
|
||||
// var formatStr strings.Builder
|
||||
// if in, ok := rsp.(*pb.UserMessage); ok {
|
||||
// out := &pb.TaskListResp{}
|
||||
// if !comm.ProtoUnmarshal(in, out) {
|
||||
// return errors.New("unmarshal err").Error()
|
||||
// }
|
||||
|
||||
// for i, v := range out.List {
|
||||
// formatStr.WriteString(fmt.Sprintf("%d- %v\n", (i + 1), v))
|
||||
// }
|
||||
// }
|
||||
// return formatStr.String()
|
||||
// },
|
||||
// },
|
||||
// common.MF(comm.ModuleTask, task.TaskSubTypeGetrecord): {
|
||||
// NavLabel: "任务数据",
|
||||
// Desc: "任务数据",
|
||||
// MainType: string(comm.ModuleTask),
|
||||
// SubType: task.TaskSubTypeGetrecord,
|
||||
// Enabled: true,
|
||||
// },
|
||||
|
||||
// common.MF(comm.ModuleTask, task.TaskSubTypeActiveList): {
|
||||
// NavLabel: "活跃度列表",
|
||||
// Desc: "用户活跃度列表",
|
||||
// MainType: string(comm.ModuleTask),
|
||||
// SubType: task.TaskSubTypeActiveList,
|
||||
// Req: &pb.TaskActiveListReq{},
|
||||
// Rsp: &pb.TaskActiveListResp{},
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleTask, task.TaskSubTypeActiveReceive): {
|
||||
// NavLabel: "活跃度领取",
|
||||
// Desc: "用户活跃度领取",
|
||||
// MainType: string(comm.ModuleTask),
|
||||
// SubType: task.TaskSubTypeActiveReceive,
|
||||
// Req: &pb.TaskActiveReceiveReq{},
|
||||
// Rsp: &pb.TaskActiveReceiveResp{},
|
||||
// Enabled: true,
|
||||
// },
|
||||
// hero
|
||||
// string(comm.ModuleHero): {
|
||||
// NavLabel: "英雄",
|
||||
// MainType: string(comm.ModuleHero),
|
||||
// Enabled: true,
|
||||
// // },
|
||||
// common.MF(comm.ModuleHero, hero.HeroSubTypeList): {
|
||||
// NavLabel: "英雄列表",
|
||||
// Desc: "英雄列表",
|
||||
// MainType: string(comm.ModuleHero),
|
||||
// SubType: hero.HeroSubTypeList,
|
||||
// Print: func(rsp proto.Message) string {
|
||||
// logrus.WithFields(logrus.Fields{"main": comm.ModuleHero, "stype": hero.HeroSubTypeList}).Debug("print")
|
||||
// var formatStr strings.Builder
|
||||
// if in, ok := rsp.(*pb.UserMessage); ok {
|
||||
// out := &pb.HeroListResp{}
|
||||
// if !comm.ProtoUnmarshal(in, out) {
|
||||
// return errors.New("unmarshal err").Error()
|
||||
// }
|
||||
// for i, v := range out.List {
|
||||
// formatStr.WriteString(fmt.Sprintf("%d- %v\n", (i + 1), v))
|
||||
// }
|
||||
// }
|
||||
// return formatStr.String()
|
||||
// },
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleHero, hero.StrengthenUplv): {
|
||||
// NavLabel: "英雄升级",
|
||||
// Desc: "英雄等级升级",
|
||||
// MainType: string(comm.ModuleHero),
|
||||
// SubType: hero.StrengthenUplv,
|
||||
// Req: &pb.HeroStrengthenUplvReq{},
|
||||
// Rsp: &pb.HeroStrengthenUplvResp{},
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleHero, hero.StrengthenUpStar): {
|
||||
// NavLabel: "英雄升星",
|
||||
// Desc: "英雄星级升级",
|
||||
// MainType: string(comm.ModuleHero),
|
||||
// SubType: hero.StrengthenUpStar,
|
||||
// Req: &pb.HeroStrengthenUpStarReq{},
|
||||
// Rsp: &pb.HeroStrengthenUpStarResp{},
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleHero, hero.DrawCard): {
|
||||
// NavLabel: "招募",
|
||||
// Desc: "抽卡招募",
|
||||
// MainType: string(comm.ModuleHero),
|
||||
// SubType: hero.DrawCard,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleHero, "info"): {
|
||||
// NavLabel: "英雄信息",
|
||||
// Desc: "英雄信息",
|
||||
// MainType: string(comm.ModuleHero),
|
||||
// SubType: "info",
|
||||
// Enabled: true,
|
||||
// },
|
||||
//equipment
|
||||
// string(comm.ModuleEquipment): {
|
||||
// NavLabel: "装备",
|
||||
// MainType: string(comm.ModuleEquipment),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleEquipment, "getlist"): {
|
||||
// NavLabel: "装备列表",
|
||||
// Desc: "装备列表",
|
||||
// MainType: string(comm.ModuleEquipment),
|
||||
// SubType: "getlist",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleEquipment, "equip"): {
|
||||
// NavLabel: "穿卸装备",
|
||||
// Desc: "穿/卸装备",
|
||||
// MainType: string(comm.ModuleEquipment),
|
||||
// SubType: "equip",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleEquipment, "upgrade"): {
|
||||
// NavLabel: "升级装备",
|
||||
// Desc: "升级装备",
|
||||
// MainType: string(comm.ModuleEquipment),
|
||||
// SubType: "upgrade",
|
||||
// Enabled: true,
|
||||
// },
|
||||
//friend
|
||||
// string(comm.ModuleFriend): {
|
||||
// NavLabel: "好友",
|
||||
// MainType: string(comm.ModuleFriend),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeRandList): {
|
||||
// NavLabel: "在线玩家",
|
||||
// Desc: "在线玩家列表",
|
||||
// MainType: string(comm.ModuleFriend),
|
||||
// SubType: friend.FriendSubTypeRandList,
|
||||
// Enabled: true
|
||||
|
||||
// },
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeList): {
|
||||
// NavLabel: "我的好友",
|
||||
// Desc: "我的好友列表",
|
||||
// MainType: string(comm.ModuleFriend),
|
||||
// SubType: friend.FriendSubTypeList,
|
||||
// Req: &pb.FriendListReq{},
|
||||
// Rsp: &pb.FriendListResp{},
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeApply): {
|
||||
// NavLabel: "好友申请",
|
||||
// Desc: "好友申请",
|
||||
// MainType: string(comm.ModuleFriend),
|
||||
// SubType: friend.FriendSubTypeApply,
|
||||
// Req: &pb.FriendApplyReq{},
|
||||
// Rsp: &pb.FriendApplyResp{},
|
||||
// Enabled: false,
|
||||
// },
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeBlacklist): {
|
||||
// NavLabel: "黑名单",
|
||||
// Desc: "黑名单列表",
|
||||
// MainType: string(comm.ModuleFriend),
|
||||
// SubType: friend.FriendSubTypeBlacklist,
|
||||
// Req: &pb.FriendBlackListReq{},
|
||||
// Rsp: &pb.FriendBlackListResp{},
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeAddBlack): {
|
||||
// NavLabel: "加黑名单",
|
||||
// Desc: "添加黑名单",
|
||||
// MainType: string(comm.ModuleFriend),
|
||||
// SubType: friend.FriendSubTypeAddBlack,
|
||||
// Req: &pb.FriendAddBlackReq{},
|
||||
// Rsp: &pb.FriendAddBlackResp{},
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeDelBlack): {
|
||||
// NavLabel: "删黑名单",
|
||||
// Desc: "删除黑名单",
|
||||
// MainType: string(comm.ModuleFriend),
|
||||
// SubType: friend.FriendSubTypeDelBlack,
|
||||
// Req: &pb.FriendDelBlackReq{},
|
||||
// Rsp: &pb.FriendDelBlackResp{},
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeAgree): {
|
||||
// NavLabel: "好友审批",
|
||||
// Desc: "好友申请审批",
|
||||
// MainType: string(comm.ModuleFriend),
|
||||
// SubType: friend.FriendSubTypeAgree,
|
||||
// Req: &pb.FriendAgreeReq{},
|
||||
// Rsp: &pb.FriendAgreeResp{},
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeSearch): {
|
||||
// NavLabel: "好友搜索",
|
||||
// Desc: "搜索好友",
|
||||
// MainType: string(comm.ModuleFriend),
|
||||
// SubType: friend.FriendSubTypeSearch,
|
||||
// Req: &pb.FriendSearchReq{},
|
||||
// Rsp: &pb.FriendSearchResp{},
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeAssistHero): {
|
||||
// NavLabel: "助战英雄",
|
||||
// Desc: "助战英雄",
|
||||
// MainType: string(comm.ModuleFriend),
|
||||
// SubType: friend.FriendSubTypeAssistHero,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeAssistlist): {
|
||||
// NavLabel: "助战列表",
|
||||
// Desc: "助战英雄列表",
|
||||
// MainType: string(comm.ModuleFriend),
|
||||
// SubType: friend.FriendSubTypeAssistlist,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeGetreward): {
|
||||
// NavLabel: "助战奖励",
|
||||
// Desc: "助战奖励",
|
||||
// MainType: string(comm.ModuleFriend),
|
||||
// SubType: friend.FriendSubTypeGetreward,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeAssistHeroList): {
|
||||
// NavLabel: "助战英雄列表",
|
||||
// Desc: "我的好友助战英雄列表",
|
||||
// MainType: string(comm.ModuleFriend),
|
||||
// SubType: friend.FriendSubTypeAssistHeroList,
|
||||
// Enabled: true,
|
||||
// },
|
||||
|
||||
// //shop
|
||||
// string(comm.ModuleShop): {
|
||||
// NavLabel: "商店",
|
||||
// MainType: string(comm.ModuleShop),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleShop, "getlist"): {
|
||||
// NavLabel: "商店列表",
|
||||
// Desc: "商店列表",
|
||||
// MainType: string(comm.ModuleShop),
|
||||
// SubType: "getlist",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleShop, "buy"): {
|
||||
// NavLabel: "购买商品",
|
||||
// Desc: "购买商品",
|
||||
// MainType: string(comm.ModuleShop),
|
||||
// SubType: "buy",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// mainline
|
||||
// string(comm.ModuleMline): {
|
||||
// NavLabel: "主线关卡",
|
||||
// MainType: string(comm.ModuleShop),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleMline, mline.MlineGetListResp): {
|
||||
// NavLabel: "主线关卡",
|
||||
// Desc: "主线关卡",
|
||||
// MainType: string(comm.ModuleMline),
|
||||
// SubType: mline.MlineGetListResp,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleMline, mline.MlineChallengeResp): {
|
||||
// NavLabel: "关卡挑战",
|
||||
// Desc: "关卡挑战",
|
||||
// MainType: string(comm.ModuleMline),
|
||||
// SubType: mline.MlineChallengeResp,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleMline, mline.MlineGetRewardResp): {
|
||||
// NavLabel: "关卡奖励",
|
||||
// Desc: "获取关卡奖励",
|
||||
// MainType: string(comm.ModuleMline),
|
||||
// SubType: mline.MlineGetRewardResp,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// //pagoda
|
||||
// string(comm.ModulePagoda): {
|
||||
// NavLabel: "魔塔",
|
||||
// MainType: string(comm.ModulePagoda),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModulePagoda, "getlist"): {
|
||||
// NavLabel: "魔塔列表",
|
||||
// Desc: "魔塔列表",
|
||||
// MainType: string(comm.ModulePagoda),
|
||||
// SubType: "getlist",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// rtask
|
||||
// string(comm.ModuleRtask): {
|
||||
// NavLabel: "随机任务",
|
||||
// MainType: string(comm.ModuleRtask),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleRtask, "rtest"): {
|
||||
// NavLabel: "测试条件",
|
||||
// Desc: "测试任务触发",
|
||||
// MainType: string(comm.ModuleRtask),
|
||||
// SubType: "rtest",
|
||||
// Enabled: true,
|
||||
// },
|
||||
//linestory
|
||||
// string(comm.ModuleLinestory): {
|
||||
// NavLabel: "支线剧情任务",
|
||||
// MainType: string(comm.ModuleLinestory),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleLinestory, linestory.LinestorySubTypeChapter): {
|
||||
// NavLabel: "支线任务",
|
||||
// Desc: "我的剧情任务",
|
||||
// MainType: string(comm.ModuleLinestory),
|
||||
// SubType: linestory.LinestorySubTypeChapter,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleLibrary, library.LibraryFetterstoryTaskResp): {
|
||||
// NavLabel: "羁绊任务",
|
||||
// Desc: "我的剧情任务",
|
||||
// MainType: string(comm.ModuleLibrary),
|
||||
// SubType: library.LibraryFetterstoryTaskResp,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// // gourmet
|
||||
// string(comm.ModuleGourmet): {
|
||||
// NavLabel: "美食馆",
|
||||
// MainType: string(comm.ModuleGourmet),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleGourmet, "getranduser"): {
|
||||
// NavLabel: "随机玩家",
|
||||
// Desc: "随机玩家",
|
||||
// MainType: string(comm.ModuleGourmet),
|
||||
// SubType: "getranduser",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// sociaty
|
||||
// string(comm.ModuleSociaty): {
|
||||
// NavLabel: "公会",
|
||||
// MainType: string(comm.ModuleSociaty),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleSociaty, sociaty.SociatySubTypeCreate): {
|
||||
// NavLabel: "公会创建",
|
||||
// Desc: "公会创建",
|
||||
// MainType: string(comm.ModuleSociaty),
|
||||
// SubType: sociaty.SociatySubTypeCreate,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleSociaty, sociaty.SociatySubTypeList): {
|
||||
// NavLabel: "公会推荐",
|
||||
// Desc: "公会列表",
|
||||
// MainType: string(comm.ModuleSociaty),
|
||||
// SubType: sociaty.SociatySubTypeList,
|
||||
// Enabled: true,
|
||||
// Print: func(rsp proto.Message) string {
|
||||
// return "不打印"
|
||||
// },
|
||||
// },
|
||||
// common.MF(comm.ModuleSociaty, sociaty.SociatySubTypeMine): {
|
||||
// NavLabel: "我的公会",
|
||||
// Desc: "我的公会",
|
||||
// MainType: string(comm.ModuleSociaty),
|
||||
// SubType: sociaty.SociatySubTypeMine,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleSociaty, sociaty.SociatySubTypeTasklist): {
|
||||
// NavLabel: "任务列表",
|
||||
// Desc: "任务列表",
|
||||
// MainType: string(comm.ModuleSociaty),
|
||||
// SubType: sociaty.SociatySubTypeTasklist,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleSociaty, sociaty.SociatySubTypeRank): {
|
||||
// NavLabel: "排行榜",
|
||||
// Desc: "排行榜",
|
||||
// MainType: string(comm.ModuleSociaty),
|
||||
// SubType: sociaty.SociatySubTypeRank,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleSociaty, "boss"): {
|
||||
// NavLabel: "BOSS",
|
||||
// Desc: "BOSS",
|
||||
// MainType: string(comm.ModuleSociaty),
|
||||
// SubType: "boss",
|
||||
// Enabled: true,
|
||||
// },
|
||||
//troll
|
||||
// string(comm.ModuleTroll): {
|
||||
// NavLabel: "巨兽",
|
||||
// MainType: string(comm.ModuleTroll),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleTroll, "getlist"): {
|
||||
// NavLabel: "列表",
|
||||
// Desc: "巨兽列表",
|
||||
// MainType: string(comm.ModuleTroll),
|
||||
// SubType: "getlist",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// growtask
|
||||
// string(comm.ModuleGrowtask): {
|
||||
// NavLabel: "成长任务",
|
||||
// MainType: string(comm.ModuleGrowtask),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleGrowtask, growtask.GrowtaskSubTypeList): {
|
||||
// NavLabel: "列表",
|
||||
// Desc: "成长任务列表",
|
||||
// MainType: string(comm.ModuleGrowtask),
|
||||
// SubType: growtask.GrowtaskSubTypeList,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// worldtask
|
||||
// string(comm.ModuleWorldtask): {
|
||||
// NavLabel: "世界任务",
|
||||
// MainType: string(comm.ModuleWorldtask),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleWorldtask, worldtask.WorldtaskSubtypeMine): {
|
||||
// NavLabel: "我的任务",
|
||||
// Desc: "世界任务剧情",
|
||||
// MainType: string(comm.ModuleWorldtask),
|
||||
// SubType: worldtask.WorldtaskSubtypeMine,
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleWorldtask, "check"): {
|
||||
// NavLabel: "模拟",
|
||||
// Desc: "世界任务自动执行模拟",
|
||||
// MainType: string(comm.ModuleWorldtask),
|
||||
// SubType: "check",
|
||||
// Enabled: true,
|
||||
// },
|
||||
common.MF("worldtask", "test"): {
|
||||
NavLabel: "触发条件",
|
||||
Desc: "触发条件",
|
||||
MainType: "worldtask",
|
||||
SubType: "test",
|
||||
Enabled: true,
|
||||
},
|
||||
// smithy
|
||||
string("smithy"): {
|
||||
NavLabel: "铁匠铺",
|
||||
MainType: string("smithy"),
|
||||
Enabled: true,
|
||||
},
|
||||
common.MF("smithy", "tasklist"): {
|
||||
NavLabel: "任务",
|
||||
Desc: "当前铁匠铺中的顾客",
|
||||
MainType: string("smithy"),
|
||||
SubType: "tasklist",
|
||||
Enabled: true,
|
||||
},
|
||||
// dispatch
|
||||
// string(comm.ModuleDispatch): {
|
||||
// NavLabel: "武馆派遣",
|
||||
// MainType: string(comm.ModuleDispatch),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleDispatch, "dispatch"): {
|
||||
// NavLabel: "派遣",
|
||||
// Desc: "派遣",
|
||||
// MainType: string(comm.ModuleDispatch),
|
||||
// SubType: "dispatch",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModulePractice, "practice"): {
|
||||
// NavLabel: "练功",
|
||||
// Desc: "练功",
|
||||
// MainType: string(comm.ModulePractice),
|
||||
// SubType: "practice",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// reputation
|
||||
// string(comm.ModuleReputation): {
|
||||
// NavLabel: "声望",
|
||||
// MainType: string(comm.ModuleReputation),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleReputation, "reputation"): {
|
||||
// NavLabel: "声望管理",
|
||||
// Desc: "声望管理",
|
||||
// MainType: string(comm.ModuleReputation),
|
||||
// SubType: "reputation",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// oldtimes
|
||||
// string(comm.ModuleOldtimes): {
|
||||
// NavLabel: "旧时光",
|
||||
// MainType: string(comm.ModuleOldtimes),
|
||||
// Enabled: true,
|
||||
// },
|
||||
// common.MF(comm.ModuleOldtimes, "oldtimes"): {
|
||||
// NavLabel: "关卡",
|
||||
// Desc: "关卡编辑器",
|
||||
// MainType: string(comm.ModuleOldtimes),
|
||||
// SubType: "oldtimes",
|
||||
// Enabled: true,
|
||||
// },
|
||||
}
|
||||
)
|
32
cmd/v2/lib/pb/task_protocol.go
Normal file
32
cmd/v2/lib/pb/task_protocol.go
Normal file
@ -0,0 +1,32 @@
|
||||
package pb
|
||||
|
||||
import (
|
||||
// "go_dreamfactory/cmd/v2/lib/common"
|
||||
// "go_dreamfactory/cmd/v2/model"
|
||||
// "go_dreamfactory/comm"
|
||||
// "go_dreamfactory/pb"
|
||||
)
|
||||
|
||||
var (
|
||||
// TaskCase = map[string]*model.TestCase{
|
||||
// common.MF(comm.ModuleAcademy, "receive"): {
|
||||
// NavLabel: "联盟学院 领取奖励",
|
||||
// Desc: "新手训练营",
|
||||
// MainType: string(comm.ModuleAcademy),
|
||||
// SubType: "receive",
|
||||
// Enabled: true,
|
||||
// Req: &pb.AcademyReceiveReq{},
|
||||
// Rsp: &pb.AcademyReceiveResp{},
|
||||
// },
|
||||
// }
|
||||
|
||||
//worldtask
|
||||
// WorldtaskCase = map[string]*model.TestCase{
|
||||
// common.MF(comm.ModuleWorldtask, "accept"): {
|
||||
// NavLabel: "接取任务",
|
||||
// MainType: string(comm.ModuleWorldtask),
|
||||
// SubType: "accept",
|
||||
// Enabled: true,
|
||||
// },
|
||||
// }
|
||||
)
|
56
cmd/v2/lib/quen.go
Normal file
56
cmd/v2/lib/quen.go
Normal file
@ -0,0 +1,56 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Queue[T any] struct {
|
||||
data []T
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
||||
func NewQueue[T any]() *Queue[T] {
|
||||
return &Queue[T]{data: make([]T, 0)}
|
||||
}
|
||||
|
||||
func (this *Queue[T]) Add(obj T) {
|
||||
this.lock.Lock()
|
||||
defer this.lock.Unlock()
|
||||
this.data = append(this.data, obj)
|
||||
}
|
||||
|
||||
func (this *Queue[T]) List() []T {
|
||||
this.lock.RLock()
|
||||
defer this.lock.RUnlock()
|
||||
list := make([]T, 0, len(this.data))
|
||||
for _, v := range this.data {
|
||||
list = append(list, v)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func (this *Queue[T]) Get(index int) (T, bool) {
|
||||
this.lock.RLock()
|
||||
defer this.lock.RUnlock()
|
||||
|
||||
var ret T
|
||||
if index < 0 || index >= len(this.data) {
|
||||
return ret, false
|
||||
}
|
||||
|
||||
return this.data[index], true
|
||||
}
|
||||
|
||||
func (this *Queue[T]) Pop() (T, error) {
|
||||
this.lock.Lock()
|
||||
defer this.lock.Unlock()
|
||||
var ret T
|
||||
if len(this.data) == 0 {
|
||||
return ret, fmt.Errorf("not found")
|
||||
}
|
||||
|
||||
pop := this.data[0]
|
||||
this.data = this.data[1:]
|
||||
return pop, nil
|
||||
}
|
110
cmd/v2/lib/storage/config.go
Normal file
110
cmd/v2/lib/storage/config.go
Normal file
@ -0,0 +1,110 @@
|
||||
package storage
|
||||
|
||||
import "go_dreamfactory/pb"
|
||||
|
||||
// 默认配置
|
||||
func NewDefaultConfig() *Config {
|
||||
return &Config{
|
||||
Pressure: PressureConfig{
|
||||
TimeoutMs: 50,
|
||||
Concurrency: 10,
|
||||
DurationS: 5,
|
||||
},
|
||||
UserCount: 100,
|
||||
UpgradeUrl: "http://10.0.0.9:8080/",
|
||||
Servers: []*ServerConfig{
|
||||
{
|
||||
SId: "df01",
|
||||
Url: "ws://119.3.89.14:9891/gateway",
|
||||
Name: "外网",
|
||||
},
|
||||
{
|
||||
SId: "df01",
|
||||
Url: "ws://10.0.0.9:7891/gateway",
|
||||
Name: "测试服",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Pressure PressureConfig `json:"Pressure,omitempty"`
|
||||
UserCount int32 `json:"UserCount,omitempty"` //用户数
|
||||
SId string `json:"sid,omitempty"` //区服ID
|
||||
WsAddr string `json:"wsAddr,omitempty"` //websocket addr
|
||||
IntervalS int32 `json:"intervalS,omitempty"` //间隔时间s
|
||||
LubanConf *LubanConfig `json:"lubanConf,omitempty"` //luban工具配置
|
||||
PbConf *ProtobufConfig `json:"pbConf,omitempty"` //Pb配置
|
||||
SyncConf *SyncConfig `json:"syncConf,omitempty"` //同步配置
|
||||
UpgradeUrl string `json:"upgradeUrl,omitempty"` //升级服务
|
||||
Servers []*ServerConfig `json:"servers,omitempty"` //区服配置
|
||||
MgoDB *MgoDB `json:"mgoDB,omitempty"` //MongoDB配置
|
||||
ServiceDBInfo *pb.ServiceDBInfo `json:"serviceDBInfo,omitempty"` //
|
||||
JsonDir string `json:"jsonDir,omitempty"` //json配置目录
|
||||
PingConf *PingConf `json:"pingConf,omitempty"` //ping配置
|
||||
MultiMgo map[string]*MgoDB `json:"multiMgo,omitempty"` //MongoDBMap
|
||||
}
|
||||
|
||||
type PingConf struct {
|
||||
Host string
|
||||
Ports string
|
||||
}
|
||||
|
||||
type MgoDB struct {
|
||||
Name string `json:"name,omitempty"` //
|
||||
Host string `json:"host,omitempty"`
|
||||
Port int32 `json:"port,omitempty"`
|
||||
User string `json:"user,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Database string `json:"database,omitempty"`
|
||||
}
|
||||
|
||||
// 压测配置
|
||||
type PressureConfig struct {
|
||||
TimeoutMs int32 `json:"timeout,omitempty"` //超时时间 毫秒
|
||||
Concurrency int32 `json:"concurrency,omitempty"` //并发量
|
||||
DurationS int32 `json:"duration,omitempty"` //持续时间 秒
|
||||
}
|
||||
|
||||
// luban
|
||||
type LubanConfig struct {
|
||||
ServerAddr string
|
||||
ProjectDir string
|
||||
WorkDir string
|
||||
Client string
|
||||
GenType string
|
||||
TmpDir string
|
||||
InputDir string //输入目录
|
||||
OutputCodeDir string //输出Code目录
|
||||
OutputJsonDir string //输出json目录
|
||||
}
|
||||
|
||||
type ProtobufConfig struct {
|
||||
ProtoDir string
|
||||
OutputDir string
|
||||
}
|
||||
|
||||
type SyncConfig struct {
|
||||
Ip string
|
||||
Port string
|
||||
UserName string
|
||||
Password string
|
||||
LocalDir string
|
||||
RemoteDir string
|
||||
|
||||
ServerIp string
|
||||
WorkDir string
|
||||
LubanCli string
|
||||
DataDir string
|
||||
JsonDir string
|
||||
|
||||
SaveDir string //保存目录
|
||||
LogDir string //远程日志目录
|
||||
Editor string //编辑器
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
SId string
|
||||
Name string
|
||||
Url string
|
||||
}
|
29
cmd/v2/lib/storage/storage.go
Normal file
29
cmd/v2/lib/storage/storage.go
Normal file
@ -0,0 +1,29 @@
|
||||
package storage
|
||||
|
||||
import "path/filepath"
|
||||
|
||||
const (
|
||||
storageRootName = "storage"
|
||||
configFileName = "config.json"
|
||||
|
||||
ID = "zhaocy.df"
|
||||
Version = "zhaocy/df/v1"
|
||||
)
|
||||
|
||||
type Storage interface {
|
||||
Root() string
|
||||
ConfigStorage
|
||||
}
|
||||
|
||||
type ConfigStorage interface {
|
||||
LoadConfig() (*Config, error)
|
||||
StoreConfig(s *Config) error
|
||||
}
|
||||
|
||||
func storageRootPath(s Storage) string {
|
||||
return filepath.Join(s.Root(), storageRootName)
|
||||
}
|
||||
|
||||
func configPath(s Storage) string {
|
||||
return filepath.Join(storageRootPath(s), configFileName)
|
||||
}
|
117
cmd/v2/lib/storage/storage_os.go
Normal file
117
cmd/v2/lib/storage/storage_os.go
Normal file
@ -0,0 +1,117 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var _ Storage = (*OSStorage)(nil)
|
||||
|
||||
type OSStorage struct {
|
||||
root string
|
||||
}
|
||||
|
||||
func NewOSStorage() (Storage, error) {
|
||||
urd, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("不能获取默认的根目录 : %w", err)
|
||||
}
|
||||
return NewOSStorageRooted(urd)
|
||||
}
|
||||
|
||||
func NewOSStorageRooted(root string) (Storage, error) {
|
||||
if !filepath.IsAbs(root) {
|
||||
return nil, fmt.Errorf("root必须是绝对路径:%s", root)
|
||||
}
|
||||
|
||||
storageRoot := filepath.Join(root, ".df")
|
||||
|
||||
s := &OSStorage{root: storageRoot}
|
||||
|
||||
mighted, err := s.migrateDeprecatedRootStorage()
|
||||
if mighted {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("找到不推荐使用的存储,但无法移动到新位置:%w", err)
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
err = s.mkdirIfNotExists(storageRootPath(s))
|
||||
return s, err
|
||||
}
|
||||
|
||||
func (s *OSStorage) Root() string {
|
||||
return s.root
|
||||
}
|
||||
|
||||
func (s *OSStorage) LoadConfig() (*Config, error) {
|
||||
configFile := configPath(s)
|
||||
f, err := os.Open(configFile)
|
||||
if os.IsNotExist(err) {
|
||||
return NewDefaultConfig(), nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return NewDefaultConfig(), fmt.Errorf("没有读到 URI:%w", err)
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
config := &Config{}
|
||||
err = json.NewDecoder(f).Decode(config)
|
||||
if err != nil {
|
||||
return NewDefaultConfig(), err
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (s *OSStorage) StoreConfig(config *Config) error {
|
||||
configFile := configPath(s)
|
||||
w, err := s.createFile(configFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer w.Close()
|
||||
|
||||
return json.NewEncoder(w).Encode(config)
|
||||
}
|
||||
|
||||
func (s *OSStorage) createFile(name string) (*os.File, error) {
|
||||
return os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
}
|
||||
|
||||
func (s *OSStorage) isExist(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return !os.IsNotExist(err)
|
||||
}
|
||||
|
||||
func (s *OSStorage) mkdirIfNotExists(dir string) error {
|
||||
if s.isExist(dir) {
|
||||
return nil
|
||||
}
|
||||
return os.MkdirAll(dir, 0700)
|
||||
}
|
||||
|
||||
// 合并弃用的根目录
|
||||
func (s *OSStorage) migrateDeprecatedRootStorage() (bool, error) {
|
||||
oldRoot, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
src := filepath.Join(oldRoot, "fyne", ID, "vvv")
|
||||
_, err = os.Stat(src)
|
||||
if os.IsNotExist(err) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
dest := storageRootPath(s)
|
||||
err = os.Rename(src, dest)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
201
cmd/v2/main.go
Normal file
201
cmd/v2/main.go
Normal file
@ -0,0 +1,201 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/cmd/v2/service"
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
"go_dreamfactory/cmd/v2/theme"
|
||||
"go_dreamfactory/cmd/v2/ui"
|
||||
"image/color"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/app"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
var (
|
||||
connService service.ConnService
|
||||
pttService service.PttService
|
||||
obs = observer.NewObserver()
|
||||
logger *logrus.Logger
|
||||
)
|
||||
|
||||
func init() {
|
||||
_ = os.Setenv("FYNE_SCALE", "0.9")
|
||||
var err error
|
||||
// initialize logger
|
||||
if err = setupLogger(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// if err = setupConfig(); err != nil {
|
||||
// fmt.Println(err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
|
||||
if err = setupWsConn(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err = setupPtt(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// create a new ui
|
||||
app := app.NewWithID("df-toolkit")
|
||||
app.SetIcon(theme.ResourceAppPng)
|
||||
|
||||
appUI, err := ui.NewUI(app, connService, pttService, obs)
|
||||
if err != nil {
|
||||
w := fyne.CurrentApp().NewWindow("错误")
|
||||
w.SetContent(canvas.NewText(err.Error(), color.RGBA{255, 0, 0, 255}))
|
||||
w.ShowAndRun()
|
||||
}
|
||||
// logLifecycle(app)
|
||||
|
||||
//创建enter
|
||||
w := fyne.CurrentApp().NewWindow("传送门")
|
||||
w.SetIcon(theme.ResourceAppPng)
|
||||
// 检查版本
|
||||
if app.Metadata().Build > 1 {
|
||||
checkVersion(app, w)
|
||||
}
|
||||
|
||||
w.SetContent(container.NewGridWithColumns(2,
|
||||
widget.NewButton("工具", func() {
|
||||
toolWindow := ui.NewToolWindow(appUI, w)
|
||||
toolWindow.CreateWindow(common.APP_NAME, 1499, 800, true)
|
||||
w.Hide()
|
||||
}),
|
||||
widget.NewButton("登服", func() {
|
||||
mainWindow := ui.NewMainWindow(appUI, w)
|
||||
mainWindow.CreateWindow(common.APP_NAME, 1499, 800, true)
|
||||
w.Hide()
|
||||
}),
|
||||
// widget.NewButton("自动化测试", func() {
|
||||
// perfWindow := ui.NewPerfWindow(appUI, w)
|
||||
// perfWindow.CreateWindow(common.APP_NAME, 800, 600, true)
|
||||
// w.Hide()
|
||||
// }),
|
||||
))
|
||||
w.SetFixedSize(true)
|
||||
w.Resize(fyne.NewSize(400, 200))
|
||||
w.CenterOnScreen()
|
||||
w.SetCloseIntercept(func() {
|
||||
app.Quit()
|
||||
})
|
||||
|
||||
logrus.WithField("version", app.Metadata().Version).Debug("app starting")
|
||||
w.Show()
|
||||
appUI.Run()
|
||||
}
|
||||
|
||||
func logLifecycle(a fyne.App) {
|
||||
a.Lifecycle().SetOnStarted(func() {
|
||||
log.Println("Lifecycle: Started")
|
||||
})
|
||||
a.Lifecycle().SetOnStopped(func() {
|
||||
log.Println("Lifecycle: Stopped")
|
||||
})
|
||||
a.Lifecycle().SetOnEnteredForeground(func() {
|
||||
log.Println("Lifecycle: Entered Foreground")
|
||||
})
|
||||
a.Lifecycle().SetOnExitedForeground(func() {
|
||||
log.Println("Lifecycle: Exited Foreground")
|
||||
})
|
||||
}
|
||||
|
||||
func setupPtt() (err error) {
|
||||
pttService = service.NewPttService(connService, obs)
|
||||
return
|
||||
}
|
||||
|
||||
func setupWsConn() (err error) {
|
||||
connService = service.NewConnService(obs)
|
||||
return
|
||||
}
|
||||
|
||||
func setupLogger() (err error) {
|
||||
logrus.SetFormatter(&logrus.JSONFormatter{
|
||||
TimestampFormat: "2006-01-02 15:04:05",
|
||||
// DisableColors: true,
|
||||
// FullTimestamp: true,
|
||||
})
|
||||
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
logrus.SetOutput(os.Stdout)
|
||||
|
||||
//设置output,默认为stderr,可以为任何io.Writer,比如文件*os.File
|
||||
file, err := os.OpenFile("robot.log", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
|
||||
writers := []io.Writer{
|
||||
file,
|
||||
os.Stdout}
|
||||
|
||||
//同时写文件和屏幕
|
||||
fileAndStdoutWriter := io.MultiWriter(writers...)
|
||||
if err == nil {
|
||||
logrus.SetOutput(fileAndStdoutWriter)
|
||||
} else {
|
||||
logrus.Fatal("failed to log to file.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// check version
|
||||
func checkVersion(app fyne.App, parent fyne.Window) {
|
||||
b, err := connService.HttpConnect("http://10.0.0.9:8080/" + "version")
|
||||
if err != nil {
|
||||
dialog.ShowError(errors.New("版本检查:"+err.Error()), parent)
|
||||
return
|
||||
}
|
||||
|
||||
oldVer := app.Metadata().Version
|
||||
parent.SetTitle(fmt.Sprintf("传送门 v%v", oldVer))
|
||||
ver := gjson.Get(string(b), "version").String()
|
||||
if strings.HasSuffix(ver, ".zip") {
|
||||
ver = strings.TrimSuffix(ver, ".zip")
|
||||
}
|
||||
logrus.WithField("version", ver).Debug("server version")
|
||||
if common.IsUpgrade(ver, oldVer) {
|
||||
chkDialog := dialog.NewConfirm("版本检查", "检查到新版本:"+ver+" 请升级后使用", func(b bool) {
|
||||
var commands = map[string]string{
|
||||
"windows": "explorer",
|
||||
"darwin": "open",
|
||||
"linux": "xdg-open",
|
||||
}
|
||||
//open browser
|
||||
open := func(uri string) error {
|
||||
// runtime.GOOS获取当前平台
|
||||
run, ok := commands[runtime.GOOS]
|
||||
if !ok {
|
||||
logrus.Errorf("don't know how to open things on %s platform", runtime.GOOS)
|
||||
}
|
||||
|
||||
cmd := exec.Command(run, uri)
|
||||
return cmd.Run()
|
||||
}
|
||||
_ = open("http://10.0.0.9:8080/")
|
||||
defer parent.Close()
|
||||
}, parent)
|
||||
chkDialog.SetConfirmText(common.BUTTON_OK)
|
||||
chkDialog.Show()
|
||||
}
|
||||
}
|
13
cmd/v2/model/gen.go
Normal file
13
cmd/v2/model/gen.go
Normal file
@ -0,0 +1,13 @@
|
||||
package model
|
||||
|
||||
type GenTool struct {
|
||||
ServerAddr string //服务地址
|
||||
ProjectDir string //项目目录
|
||||
TmpDir string //临时目录
|
||||
Client string //Client 文件路径
|
||||
WorkDir string //工作目录
|
||||
InputDir string //输入目录
|
||||
OutputCodeDir string //输出Code目录
|
||||
OutputJsonDir string //输出json目录
|
||||
GenType string //生成类型
|
||||
}
|
24
cmd/v2/model/item.go
Normal file
24
cmd/v2/model/item.go
Normal file
@ -0,0 +1,24 @@
|
||||
package model
|
||||
|
||||
type ItemModel struct {
|
||||
Id string
|
||||
Label string
|
||||
}
|
||||
|
||||
type ItemModelList struct {
|
||||
DataList []*ItemModel
|
||||
}
|
||||
|
||||
func NewItemModelList() *ItemModelList {
|
||||
return &ItemModelList{
|
||||
DataList: make([]*ItemModel, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ItemModelList) AsInterfaceArray() []interface{} {
|
||||
rs := make([]interface{}, len(s.DataList))
|
||||
for i, v := range s.DataList {
|
||||
rs[i] = v
|
||||
}
|
||||
return rs
|
||||
}
|
7
cmd/v2/model/login.go
Normal file
7
cmd/v2/model/login.go
Normal file
@ -0,0 +1,7 @@
|
||||
package model
|
||||
|
||||
type LoginParam struct {
|
||||
Account string `json:"account"`
|
||||
ServerId string `json:"serverId"`
|
||||
TimeStamp int64 `json:"timestamp"`
|
||||
}
|
6
cmd/v2/model/pbconf.go
Normal file
6
cmd/v2/model/pbconf.go
Normal file
@ -0,0 +1,6 @@
|
||||
package model
|
||||
|
||||
type PbConfModel struct {
|
||||
ProtoDir string //项目目录
|
||||
OutputDir string //输出目录
|
||||
}
|
29
cmd/v2/model/push.go
Normal file
29
cmd/v2/model/push.go
Normal file
@ -0,0 +1,29 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"go_dreamfactory/pb"
|
||||
)
|
||||
|
||||
type PushModel struct {
|
||||
MethodName string
|
||||
DataTime string
|
||||
Msg *pb.UserMessage
|
||||
}
|
||||
|
||||
type PushModelList struct {
|
||||
DataList []*PushModel
|
||||
}
|
||||
|
||||
func NewPushModelList() *PushModelList {
|
||||
return &PushModelList{
|
||||
DataList: make([]*PushModel, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *PushModelList) AsInterfaceArray() []interface{} {
|
||||
rs := make([]interface{}, len(s.DataList), len(s.DataList))
|
||||
for i := range s.DataList {
|
||||
rs[i] = s.DataList[i]
|
||||
}
|
||||
return rs
|
||||
}
|
21
cmd/v2/model/ssh.go
Normal file
21
cmd/v2/model/ssh.go
Normal file
@ -0,0 +1,21 @@
|
||||
package model
|
||||
|
||||
type SSHModel struct {
|
||||
Ip string
|
||||
Port string
|
||||
UserName string
|
||||
Password string
|
||||
LocalDir string
|
||||
RemoteDir string
|
||||
/////
|
||||
ServerIp string
|
||||
WorkDir string
|
||||
LubanCli string
|
||||
DataDir string
|
||||
JsonDir string
|
||||
|
||||
//
|
||||
SaveDir string //保存目录
|
||||
LogDir string //远程日志目录
|
||||
Editor string //编辑器
|
||||
}
|
17
cmd/v2/model/testcase.go
Normal file
17
cmd/v2/model/testcase.go
Normal file
@ -0,0 +1,17 @@
|
||||
package model
|
||||
|
||||
import "google.golang.org/protobuf/proto"
|
||||
|
||||
type TestCase struct {
|
||||
Id string //用例ID 如果没有指定,会自动赋值uuid
|
||||
NavLabel string //菜单名称
|
||||
Desc string //用例描述
|
||||
MainType string //协议类型 L1
|
||||
SubType string //协议类型 L2
|
||||
Req proto.Message //请求类型
|
||||
Rsp proto.Message //响应类型
|
||||
Enabled bool //是否启用
|
||||
// View MyCaseView //视图
|
||||
Print func(rsp proto.Message) string //定义打印
|
||||
Sort int32 //顺序号
|
||||
}
|
36
cmd/v2/readme.md
Normal file
36
cmd/v2/readme.md
Normal file
@ -0,0 +1,36 @@
|
||||
## install tool
|
||||
|
||||
<!-- https://sourceforge.net/projects/mingw/files/Installer/mingw-get-setup.exe/download -->
|
||||
|
||||
go install fyne.io/fyne/v2/cmd/fyne@latest
|
||||
|
||||
## install font
|
||||
|
||||
### fyne CLI 打包
|
||||
|
||||
fyne bundle msyh.ttc >> bundled.go
|
||||
-- 打包粗体
|
||||
fyne bundle -append msyhbd.ttc >> bundled.go
|
||||
(不要使用powershell 或vscode自带终端)
|
||||
|
||||
## icon
|
||||
|
||||
1.
|
||||
将静态资源编译为 go 文件
|
||||
fyne bundle fav.png >> bundled.go
|
||||
如果是要追加资源
|
||||
fyne bundle -append image2.jpg >> bundled.go
|
||||
|
||||
2.
|
||||
a := app.New()
|
||||
a.SetIcon(resourceFavPng)
|
||||
|
||||
## package
|
||||
|
||||
fyne package --name robotGUI-1.0.0 -os windows -icon Icon.png
|
||||
|
||||
## 开发协议参数表单
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
14
cmd/v2/robot.log
Normal file
14
cmd/v2/robot.log
Normal file
@ -0,0 +1,14 @@
|
||||
{"level":"debug","msg":"app starting","time":"2023-06-09 21:54:05","version":"0.0.1"}
|
||||
{"level":"debug","msg":"choose server","server":"01区","sid":"dfz01","time":"2023-06-09 21:54:08"}
|
||||
{"account":"6911","level":"debug","msg":"submit login","time":"2023-06-09 21:54:12"}
|
||||
{"level":"info","mainType":"user","msg":"登录","params":{"account":"6911","sid":"dfz01","area":0,"channel":0,"vcode":0,"vname":""},"subType":"login","time":"2023-06-09 21:54:12"}
|
||||
{"idx":2,"lbl":"昵称","level":"debug","msg":"更新Prop","time":"2023-06-09 21:54:12","val":"Piratemountain"}
|
||||
{"id":"worldtask","level":"warning","msg":"Missing tutorial panel","time":"2023-06-09 21:54:14"}
|
||||
{"id":"worldtask","level":"warning","msg":"Missing tutorial panel","time":"2023-06-09 21:54:14"}
|
||||
{"id":"worldtask","level":"warning","msg":"Missing tutorial panel","time":"2023-06-09 21:54:14"}
|
||||
{"id":"worldtask","level":"warning","msg":"Missing tutorial panel","time":"2023-06-09 21:54:14"}
|
||||
{"id":"worldtask","level":"warning","msg":"Missing tutorial panel","time":"2023-06-09 21:54:14"}
|
||||
{"id":"worldtask","level":"warning","msg":"Missing tutorial panel","time":"2023-06-09 21:54:15"}
|
||||
{"level":"debug","mainType":"smithy","msg":"select","subType":"tasklist","time":"2023-06-09 21:54:15"}
|
||||
{"level":"error","msg":"readMessage err:read tcp 10.0.0.238:14482-\u003e10.0.0.238:7891: wsarecv: An existing connection was forcibly closed by the remote host.","time":"2023-06-09 21:54:31"}
|
||||
{"level":"debug","msg":"即将与服务器断开链接","time":"2023-06-09 21:54:32"}
|
62
cmd/v2/service/assistant_test.go
Normal file
62
cmd/v2/service/assistant_test.go
Normal file
@ -0,0 +1,62 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/lib"
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/comm"
|
||||
"go_dreamfactory/pb"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Pallinder/go-randomdata"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func loginReq() ([]byte, error) {
|
||||
head := &pb.UserMessage{MainType: "user", SubType: "login"}
|
||||
sid := "dfz"
|
||||
account := randomdata.SillyName()
|
||||
head.Sec = common.BuildSecStr(sid, account)
|
||||
if comm.ProtoMarshal(&pb.UserLoginReq{
|
||||
Sid: sid,
|
||||
Account: account,
|
||||
}, head) {
|
||||
data, err := proto.Marshal(head)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func TestStart(t *testing.T) {
|
||||
wsAddr := "ws://10.0.0.238:7891/gateway"
|
||||
h, err := NewWsCli(wsAddr, 2*time.Second)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
b, err := loginReq()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h.SetReq(b, false)
|
||||
param := lib.ParamMgr{
|
||||
Caller: h,
|
||||
Timeout: 50 * time.Millisecond,
|
||||
Lps: uint32(1),
|
||||
Duration: 5 * time.Second,
|
||||
ResultCh: make(chan *lib.CallResult, 50),
|
||||
}
|
||||
a, err := lib.NewAssistant(nil, param)
|
||||
if err != nil {
|
||||
t.Fatalf("AI助手初始化错误: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
a.Start()
|
||||
|
||||
a.ShowResult()
|
||||
}
|
184
cmd/v2/service/connService.go
Normal file
184
cmd/v2/service/connService.go
Normal file
@ -0,0 +1,184 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/cmd/v2/model"
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
"go_dreamfactory/comm"
|
||||
"go_dreamfactory/pb"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
conn *ConnServiceImpl
|
||||
)
|
||||
|
||||
type ConnService interface {
|
||||
WsConnect(wsUrl string) error
|
||||
HttpConnect(url string) ([]byte, error)
|
||||
SendMsg(msg *pb.UserMessage, rsp proto.Message) (err error)
|
||||
ReceiveMsg() (errdata *pb.ErrorData, msg *pb.UserMessage)
|
||||
ListenerPush()
|
||||
Close()
|
||||
}
|
||||
|
||||
type ConnServiceImpl struct {
|
||||
ws *websocket.Conn
|
||||
obs observer.Observer
|
||||
}
|
||||
|
||||
func NewConnService(obs observer.Observer) ConnService {
|
||||
conn = &ConnServiceImpl{obs: obs}
|
||||
return conn
|
||||
}
|
||||
|
||||
func GetConnService() *ConnServiceImpl {
|
||||
return conn
|
||||
}
|
||||
|
||||
// connect ...
|
||||
func (c *ConnServiceImpl) WsConnect(wsUrl string) error {
|
||||
dialer := &websocket.Dialer{
|
||||
HandshakeTimeout: 5 * time.Second,
|
||||
}
|
||||
ws, _, err := dialer.Dial(wsUrl, nil)
|
||||
if err != nil {
|
||||
logrus.Errorf("websocket conn err:%v", err)
|
||||
return err
|
||||
}
|
||||
c.ws = ws
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ConnServiceImpl) HttpConnect(url string) ([]byte, error) {
|
||||
res, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
return ioutil.ReadAll(res.Body)
|
||||
}
|
||||
|
||||
// listener push
|
||||
func (c *ConnServiceImpl) ListenerPush() {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logrus.Errorf("listenerPush err: %v", err)
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
for {
|
||||
// time.Sleep(time.Millisecond * 200)
|
||||
msg := &pb.UserMessage{}
|
||||
_, data, err := c.ws.ReadMessage()
|
||||
if err != nil {
|
||||
logrus.Errorf("readMessage err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = proto.Unmarshal(data, msg); err != nil {
|
||||
return
|
||||
}
|
||||
// logrus.WithFields(
|
||||
// logrus.Fields{"MainType": msg.MainType, "SubType": msg.SubType},
|
||||
// ).Debug(msg.Data.TypeUrl)
|
||||
|
||||
methodStr := msg.Data.TypeUrl
|
||||
methodName := common.SubStr(methodStr, 20, len(methodStr))
|
||||
p := &model.PushModel{
|
||||
MethodName: methodName,
|
||||
DataTime: time.Now().Format(time.RFC3339),
|
||||
Msg: msg,
|
||||
}
|
||||
// logrus.WithFields(
|
||||
// logrus.Fields{"MainType": msg.MainType, "SubType": msg.SubType},
|
||||
// ).Debug(methodName)
|
||||
|
||||
renderRespPanel := func(p *model.PushModel) {
|
||||
c.obs.Notify(observer.EVENT_REQ_RSP, p.Msg)
|
||||
}
|
||||
|
||||
if strings.HasSuffix(methodName, "Push") {
|
||||
c.obs.Notify(observer.EVENT_APP_MONI, p)
|
||||
c.obs.Notify(observer.EVENT_APP_MONI_EX, msg)
|
||||
c.obs.Notify(observer.EVENT_USER_CHANGE, p)
|
||||
if methodName == "NotifyErrorNotifyPush" {
|
||||
renderRespPanel(p)
|
||||
}
|
||||
} else {
|
||||
//render appTestcase respPanel
|
||||
renderRespPanel(p)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
// SendMsg ....
|
||||
func (c *ConnServiceImpl) SendMsg(msg *pb.UserMessage, rsp proto.Message) (err error) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logrus.Errorf("sendMsg %v", err)
|
||||
}
|
||||
}()
|
||||
// msg.Sec = r.BuildSecStr()
|
||||
if comm.ProtoMarshal(rsp, msg) {
|
||||
if data, err := proto.Marshal(msg); err != nil {
|
||||
return err
|
||||
} else {
|
||||
return c.ws.WriteMessage(websocket.BinaryMessage, data)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ReceiveMsg ....
|
||||
func (c *ConnServiceImpl) ReceiveMsg() (errdata *pb.ErrorData, msg *pb.UserMessage) {
|
||||
msg = &pb.UserMessage{}
|
||||
_, data, err := c.ws.ReadMessage()
|
||||
if err != nil {
|
||||
logrus.Errorf("readMessage err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = proto.Unmarshal(data, msg); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if errdata = c.handleNotify(msg); errdata != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// err notify
|
||||
func (c *ConnServiceImpl) handleNotify(msg *pb.UserMessage) (errdata *pb.ErrorData) {
|
||||
if msg.MainType == "notify" && msg.SubType == "errornotify" {
|
||||
rsp := &pb.NotifyErrorNotifyPush{}
|
||||
if !comm.ProtoUnmarshal(msg, rsp) {
|
||||
errdata = &pb.ErrorData{
|
||||
Code: pb.ErrorCode_PbError,
|
||||
}
|
||||
return
|
||||
}
|
||||
errdata = &pb.ErrorData{
|
||||
Code: rsp.Code,
|
||||
}
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *ConnServiceImpl) Close() {
|
||||
if err := c.ws.Close(); err != nil {
|
||||
logrus.Errorf("close ws conn err: %v", err)
|
||||
}
|
||||
}
|
22
cmd/v2/service/observer/event.go
Normal file
22
cmd/v2/service/observer/event.go
Normal file
@ -0,0 +1,22 @@
|
||||
package observer
|
||||
|
||||
const (
|
||||
EVENT_PING = "ping"
|
||||
//用户详情
|
||||
EVENT_USERINFO Event = "userinfo"
|
||||
//协议推送
|
||||
EVENT_APP_MONI Event = "push"
|
||||
EVENT_APP_MONI_EX Event = "push_ex"
|
||||
// 用户数据变化
|
||||
EVENT_USER_CHANGE Event = "chanage"
|
||||
//测试用例响应事件
|
||||
EVENT_REQ_RSP Event = "response"
|
||||
// 清空 ui数据事件
|
||||
EVENT_UI_CLEAN Event = "uiclean"
|
||||
// 请求响应计时
|
||||
EVENT_RST = "ctime"
|
||||
|
||||
// 测试结果
|
||||
EVENT_RESULT = "result"
|
||||
EVENT_FINISH = "finish"
|
||||
)
|
56
cmd/v2/service/observer/observer.go
Normal file
56
cmd/v2/service/observer/observer.go
Normal file
@ -0,0 +1,56 @@
|
||||
package observer
|
||||
|
||||
import "sync"
|
||||
|
||||
type (
|
||||
Event string
|
||||
|
||||
OnNotify func(data interface{}, args ...interface{})
|
||||
|
||||
Listener struct {
|
||||
OnNotify OnNotify
|
||||
}
|
||||
|
||||
Observer interface {
|
||||
AddListener(event Event, listener Listener)
|
||||
Remove(event Event)
|
||||
Notify(event Event, data interface{}, args ...interface{})
|
||||
}
|
||||
|
||||
ObserverImpl struct {
|
||||
listeners map[Event][]Listener
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
obs *ObserverImpl
|
||||
singletonObserver sync.Once
|
||||
)
|
||||
|
||||
func NewObserver() *ObserverImpl {
|
||||
singletonObserver.Do(func() {
|
||||
obs = &ObserverImpl{}
|
||||
})
|
||||
return obs
|
||||
}
|
||||
|
||||
func (o *ObserverImpl) AddListener(event Event, listener Listener) {
|
||||
if o.listeners == nil {
|
||||
o.listeners = map[Event][]Listener{}
|
||||
}
|
||||
o.listeners[event] = append(o.listeners[event], listener)
|
||||
}
|
||||
|
||||
func (o *ObserverImpl) Remove(event Event) {
|
||||
delete(o.listeners, event)
|
||||
}
|
||||
|
||||
func (o *ObserverImpl) Notify(event Event, data interface{}, args ...interface{}) {
|
||||
if listeners, ok := o.listeners[event]; !ok {
|
||||
return
|
||||
} else {
|
||||
for _, listener := range listeners {
|
||||
go listener.OnNotify(data, args...)
|
||||
}
|
||||
}
|
||||
}
|
124
cmd/v2/service/pttService.go
Normal file
124
cmd/v2/service/pttService.go
Normal file
@ -0,0 +1,124 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
|
||||
// "go_dreamfactory/modules/user"
|
||||
"go_dreamfactory/pb"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
ptt PttService
|
||||
)
|
||||
|
||||
type PttService interface {
|
||||
Login(sid, account string) (errdata *pb.ErrorData)
|
||||
CreateRole(nickName string, gender, figure int32) (errdata *pb.ErrorData)
|
||||
GetUser() *UserInfo
|
||||
SetUser(dbUser *pb.DBUser, dbUserExpand *pb.DBUserExpand)
|
||||
SendToClient(mainType, subType string, rsp proto.Message) error
|
||||
|
||||
Ping(sid, account string)
|
||||
}
|
||||
|
||||
type PttServiceImpl struct {
|
||||
connService ConnService
|
||||
user *UserInfo
|
||||
obs observer.Observer
|
||||
}
|
||||
|
||||
type UserInfo struct {
|
||||
DbUser *pb.DBUser
|
||||
DbUserExpand *pb.DBUserExpand
|
||||
}
|
||||
|
||||
func NewPttService(connService ConnService, obs observer.Observer) PttService {
|
||||
ptt = &PttServiceImpl{
|
||||
connService: connService,
|
||||
obs: obs,
|
||||
}
|
||||
return ptt
|
||||
}
|
||||
|
||||
func GetPttService() PttService {
|
||||
return ptt
|
||||
}
|
||||
|
||||
func (p *PttServiceImpl) GetUser() *UserInfo {
|
||||
return p.user
|
||||
}
|
||||
|
||||
func (p *PttServiceImpl) SetUser(dbUser *pb.DBUser, dbUserExpand *pb.DBUserExpand) {
|
||||
p.user = &UserInfo{DbUser: dbUser, DbUserExpand: dbUserExpand}
|
||||
}
|
||||
|
||||
func (p *PttServiceImpl) SendToClient(mainType, subType string, rsp proto.Message) (err error) {
|
||||
msg := &pb.UserMessage{MainType: mainType, SubType: subType}
|
||||
msg.Sec = common.BuildSecStr(p.user.DbUser.Sid, p.user.DbUser.Binduid)
|
||||
now := time.Now()
|
||||
if err = p.connService.SendMsg(msg, rsp); err != nil {
|
||||
logrus.WithField("发送错误:", err).Error(err)
|
||||
return err
|
||||
}
|
||||
p.obs.Notify(observer.EVENT_RST, now)
|
||||
return
|
||||
}
|
||||
|
||||
// Login
|
||||
func (p *PttServiceImpl) Login(sid, account string) (errdata *pb.ErrorData) {
|
||||
head := &pb.UserMessage{MainType: string("user"), SubType: "login"}
|
||||
head.Sec = common.BuildSecStr(sid, account)
|
||||
req := &pb.UserLoginReq{
|
||||
Account: account,
|
||||
Sid: sid,
|
||||
}
|
||||
if err := p.connService.SendMsg(head, req); err != nil {
|
||||
errdata = &pb.ErrorData{
|
||||
Code: pb.ErrorCode_SystemError,
|
||||
}
|
||||
logrus.WithField("err", err).Error("Login")
|
||||
return
|
||||
}
|
||||
logrus.WithFields(logrus.Fields{common.MainType: string("user"), common.SubType: "login",
|
||||
common.Params: req}).Info("登录")
|
||||
return
|
||||
}
|
||||
|
||||
func (p *PttServiceImpl) Ping(sid, account string) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logrus.Errorf("Ping sid:%v account:%v err:%v", sid, account, err)
|
||||
}
|
||||
}()
|
||||
head := &pb.UserMessage{MainType: string("gateway"), SubType: "heartbeat"}
|
||||
head.Sec = common.BuildSecStr(sid, account)
|
||||
if err := p.connService.SendMsg(head, &pb.GatewayHeartbeatReq{}); err != nil {
|
||||
p.obs.Notify(observer.EVENT_PING, err)
|
||||
return
|
||||
}
|
||||
// logrus.Debug("Ping")
|
||||
return
|
||||
}
|
||||
|
||||
// create role
|
||||
func (p *PttServiceImpl) CreateRole(nickName string, gender, figure int32) (errdata *pb.ErrorData) {
|
||||
head := &pb.UserMessage{MainType: string("user"), SubType: "create"}
|
||||
head.Sec = common.BuildSecStr(p.user.DbUser.Sid, p.user.DbUser.Binduid)
|
||||
if err := p.connService.SendMsg(head, &pb.UserCreateReq{
|
||||
NickName: nickName,
|
||||
Figure: figure,
|
||||
Gender: gender,
|
||||
}); err != nil {
|
||||
errdata = &pb.ErrorData{
|
||||
Code: pb.ErrorCode_SystemError,
|
||||
}
|
||||
logrus.WithField("err", err).Error("CreateRole")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
378
cmd/v2/service/sshService.go
Normal file
378
cmd/v2/service/sshService.go
Normal file
@ -0,0 +1,378 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"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 //执行结果
|
||||
}
|
||||
|
||||
func NewSSHService() *SSHService {
|
||||
ss := &SSHService{}
|
||||
return ss
|
||||
}
|
||||
|
||||
func (ss *SSHService) Connect(user, password, host, key string, port int, cipherList []string) error {
|
||||
var (
|
||||
auth []ssh.AuthMethod //认证方式
|
||||
addr string
|
||||
clientConfig *ssh.ClientConfig
|
||||
config ssh.Config
|
||||
err error
|
||||
)
|
||||
auth = make([]ssh.AuthMethod, 0)
|
||||
if key == "" {
|
||||
// 密码认证
|
||||
auth = append(auth, ssh.Password(password))
|
||||
} else {
|
||||
// 秘钥认证
|
||||
pemBytes, err := ioutil.ReadFile(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var signer ssh.Signer
|
||||
if password == "" {
|
||||
signer, err = ssh.ParsePrivateKey(pemBytes)
|
||||
} else {
|
||||
signer, err = ssh.ParsePrivateKeyWithPassphrase(pemBytes, []byte(password))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 加载秘钥
|
||||
auth = append(auth, ssh.PublicKeys(signer))
|
||||
}
|
||||
|
||||
// 设置ssh 的配置参数
|
||||
if len(cipherList) == 0 {
|
||||
config = ssh.Config{
|
||||
// 连接所允许的加密算法, go的SSH包允许的算法
|
||||
Ciphers: []string{"aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "aes192-cbc", "aes256-cbc"},
|
||||
}
|
||||
} else {
|
||||
config = ssh.Config{
|
||||
Ciphers: cipherList,
|
||||
}
|
||||
}
|
||||
|
||||
clientConfig = &ssh.ClientConfig{
|
||||
User: user,
|
||||
Auth: auth,
|
||||
Timeout: time.Second * 30,
|
||||
Config: config,
|
||||
// 默认密钥不受信任时,Go 的 ssh 包会在 HostKeyCallback 里把连接干掉(1.8 之后加的应该)。但是我们使用用户名密码连接的时候,这个太正常了,所以让他 return nil 就好了
|
||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
addr = fmt.Sprintf("%s:%d", host, port)
|
||||
|
||||
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")
|
||||
}
|
||||
var err error
|
||||
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
|
||||
err error
|
||||
)
|
||||
|
||||
//获取session,这个session是用来远程执行操作的
|
||||
if session, err = ss.Client.NewSession(); err != nil {
|
||||
logrus.Errorf("error newsession:%v", err)
|
||||
}
|
||||
// 使用 session.Shell() 模拟终端时,所建立的终端参数
|
||||
modes := ssh.TerminalModes{
|
||||
ssh.ECHO: 0, //disable echoing
|
||||
ssh.TTY_OP_ISPEED: 14400, //input speed=14.4kbaud
|
||||
ssh.TTY_OP_OSPEED: 14400,
|
||||
}
|
||||
|
||||
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
|
||||
//执行shell
|
||||
if output, err := session.CombinedOutput(shell); err != nil {
|
||||
logrus.Errorf("error CombinedOutput:%v", err)
|
||||
} else {
|
||||
ss.LastResult = string(output)
|
||||
}
|
||||
}
|
||||
|
||||
//单个copy
|
||||
func (ss *SSHService) ScpCopy(localFilePath, remoteDir string) error {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
|
||||
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 sftpCli.Close()
|
||||
|
||||
srcFile, err := os.Open(localFilePath)
|
||||
if err != nil {
|
||||
log.Println("scpCopy:", err)
|
||||
return err
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
//批量copy
|
||||
func (ss *SSHService) BatchScpCoy(cfs []CopyFiles, remoteDir string) error {
|
||||
var err 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 {
|
||||
return 0, fmt.Errorf("new sftp client error: %w", err)
|
||||
}
|
||||
defer sftpClient.Close()
|
||||
// source, err := sftpClient.Open(srcFileName)
|
||||
// if err != nil {
|
||||
// return 0, fmt.Errorf("sftp client open src file error: %w", err)
|
||||
// }
|
||||
// defer source.Close()
|
||||
srcFile, err := os.Open(srcFileName)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("open local file error: %w", err)
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
var remoteFileName = path.Base(srcFileName)
|
||||
dstFile, err := sftpClient.Create(path.Join(targetDir, remoteFileName))
|
||||
if err != nil {
|
||||
fmt.Errorf("scpCopy:%v", err)
|
||||
return 0, err
|
||||
}
|
||||
// n, err := io.Copy(target, source)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("copy file error: %w", err)
|
||||
}
|
||||
defer dstFile.Close()
|
||||
|
||||
buf := make([]byte, 1024)
|
||||
n := 0
|
||||
for {
|
||||
n, _ = srcFile.Read(buf)
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
dstFile.Write(buf[0:n])
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
//Download
|
||||
func (ss *SSHService) ScpDownload(localDir, remoteFilePath string) error {
|
||||
var err error
|
||||
sftpCli, err = ss.getSftp()
|
||||
if err != nil {
|
||||
return fmt.Errorf("new sftp client error: %w", err)
|
||||
}
|
||||
|
||||
remoteFile, err := sftpCli.Open(remoteFilePath)
|
||||
if err != nil {
|
||||
log.Println("scpCopy:", err)
|
||||
return err
|
||||
}
|
||||
defer remoteFile.Close()
|
||||
|
||||
fileName := path.Base(remoteFile.Name())
|
||||
|
||||
if err := os.MkdirAll(localDir, fs.ModePerm); err != nil {
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
target, err := os.OpenFile(localDir+fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, fs.ModePerm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open local file error: %w", err)
|
||||
}
|
||||
defer target.Close()
|
||||
|
||||
_, err = io.Copy(target, remoteFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("write file error: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ss *SSHService) GetRemoteDir(remoteDir string) (files []File, err error) {
|
||||
sftpCli, err = ss.getSftp()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("new sftp client error: %w", err)
|
||||
}
|
||||
|
||||
remoteFiles, err := sftpCli.ReadDir(remoteDir)
|
||||
if err != nil {
|
||||
log.Println("read remote Dir:", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, f := range remoteFiles {
|
||||
fi := File{
|
||||
FileName: f.Name(),
|
||||
FilePath: filepath.Join(remoteDir, f.Name()),
|
||||
Size: f.Size(),
|
||||
}
|
||||
files = append(files, fi)
|
||||
// logrus.WithFields(logrus.Fields{"name": f.Name(), "size": f.Size()}).Debug("远程日志文件")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (ss *SSHService) BatchScpDownload(localDir, remoteDir string) error {
|
||||
var err error
|
||||
sftpCli, err = ss.getSftp()
|
||||
if err != nil {
|
||||
return fmt.Errorf("new sftp client error: %w", err)
|
||||
}
|
||||
|
||||
remoteFiles, err := sftpCli.ReadDir(remoteDir)
|
||||
if err != nil {
|
||||
log.Println("read remote Dir:", err)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, f := range remoteFiles {
|
||||
if err := ss.ScpDownload(localDir, filepath.Join(remoteDir, f.Name())); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type CopyFiles struct {
|
||||
Dir string
|
||||
FileName string
|
||||
}
|
||||
|
||||
type File struct {
|
||||
FileName string
|
||||
FilePath string
|
||||
Size int64
|
||||
}
|
87
cmd/v2/service/ssh_test.go
Normal file
87
cmd/v2/service/ssh_test.go
Normal file
@ -0,0 +1,87 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
username = "root"
|
||||
password = "Legu.cc()123"
|
||||
ip = "10.0.0.9"
|
||||
port = 22
|
||||
cmd = "ls"
|
||||
cmds = "cd /home/liwei/go_dreamfactory&&git pull&&exit" //exit结尾,否则程序不会退出
|
||||
)
|
||||
|
||||
func TestRunShell(t *testing.T) {
|
||||
ciphers := []string{}
|
||||
ssh := &SSHService{}
|
||||
|
||||
err := ssh.Connect(username, password, ip, "", port, ciphers)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// ssh.RunShell("cd /opt")
|
||||
ssh.RunShell(cmds)
|
||||
|
||||
}
|
||||
|
||||
func TestScp(t *testing.T) {
|
||||
ciphers := []string{}
|
||||
ssh := &SSHService{}
|
||||
|
||||
err := ssh.Connect(username, password, ip, "", port, ciphers)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
func TestScpDown(t *testing.T) {
|
||||
ciphers := []string{}
|
||||
ssh := &SSHService{}
|
||||
|
||||
err := ssh.Connect(username, password, ip, "", port, ciphers)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
sftpCli, err = ssh.getSftp()
|
||||
if err != nil {
|
||||
fmt.Errorf("new sftp client error: %w", err)
|
||||
}
|
||||
|
||||
remoteFiles, err := sftpCli.ReadDir("/home/liwei/go_dreamfactory/bin/log")
|
||||
if err != nil {
|
||||
log.Println("scpCopy:", err)
|
||||
}
|
||||
|
||||
for _, v := range remoteFiles {
|
||||
fmt.Println(v.Name())
|
||||
if err := ssh.ScpDownload("G:/log/", "/home/liwei/go_dreamfactory/bin/log/"+v.Name()); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
229
cmd/v2/service/wsCli.go
Normal file
229
cmd/v2/service/wsCli.go
Normal file
@ -0,0 +1,229 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"go_dreamfactory/cmd/v2/lib"
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/comm"
|
||||
"go_dreamfactory/lego/sys/log"
|
||||
"go_dreamfactory/pb"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/tidwall/gjson"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type WsCli struct {
|
||||
addr string
|
||||
conn *websocket.Conn
|
||||
// reqData []byte //请求数据
|
||||
uid string
|
||||
reqDatas *lib.Queue[[]byte]
|
||||
conns sync.Map
|
||||
flag bool
|
||||
reqData []byte
|
||||
}
|
||||
|
||||
func NewWsCli(addr string, timeout time.Duration) (lib.Handler, error) {
|
||||
cli := &WsCli{
|
||||
addr: addr,
|
||||
reqDatas: lib.NewQueue[[]byte](),
|
||||
}
|
||||
// if err := cli.connect(timeout); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
return cli, nil
|
||||
}
|
||||
|
||||
func (cli *WsCli) GetConnMap() sync.Map {
|
||||
return cli.conns
|
||||
}
|
||||
|
||||
func (cli *WsCli) connect(timeout time.Duration) error {
|
||||
if cli.conn == nil {
|
||||
dialer := &websocket.Dialer{
|
||||
HandshakeTimeout: 2 * time.Second,
|
||||
}
|
||||
conn, _, err := dialer.Dial(cli.addr, nil)
|
||||
if err != nil {
|
||||
logrus.Errorf("websocket conn err:%v", err)
|
||||
return err
|
||||
}
|
||||
cli.conn = conn
|
||||
}
|
||||
|
||||
// ping
|
||||
// go func() {
|
||||
// timer := time.NewTimer(2 * time.Second)
|
||||
// for {
|
||||
// timer.Reset(2 * time.Second)
|
||||
// <-timer.C
|
||||
// if err := cli.ws.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// }()
|
||||
return nil
|
||||
}
|
||||
|
||||
// 检查相应
|
||||
func (cli *WsCli) checkResp(data []byte) bool {
|
||||
msg := &pb.UserMessage{}
|
||||
if err := proto.Unmarshal(data, msg); err != nil {
|
||||
logrus.Error("结果解析失败")
|
||||
return false
|
||||
}
|
||||
if msg.MainType == "user" && msg.SubType == "login" {
|
||||
rsp := &pb.UserLoginResp{}
|
||||
if !comm.ProtoUnmarshal(msg, rsp) {
|
||||
logrus.Error("unmarshal err")
|
||||
return false
|
||||
}
|
||||
|
||||
if rsp.Data != nil {
|
||||
if rsp.Data.Uid != "" {
|
||||
logrus.WithField("uid", rsp.Data.Uid).Debug("登录响应")
|
||||
cli.uid = rsp.Data.Uid
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
if cli.uid != "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查推送(包括错误推送)
|
||||
func (cli *WsCli) checkPush(data []byte) bool {
|
||||
msg := &pb.UserMessage{}
|
||||
if err := proto.Unmarshal(data, msg); err != nil {
|
||||
logrus.Error("结果解析失败")
|
||||
return false
|
||||
}
|
||||
methodStr := msg.Data.TypeUrl
|
||||
methodName := common.SubStr(methodStr, 20, len(methodStr))
|
||||
|
||||
if strings.HasSuffix(methodName, "Push") {
|
||||
if methodName == "NotifyErrorNotifyPush" {
|
||||
push := &pb.NotifyErrorNotifyPush{}
|
||||
if !comm.ProtoUnmarshal(msg, push) {
|
||||
logrus.Error("unmarsh err")
|
||||
return false
|
||||
}
|
||||
logrus.WithField("methodName", methodName).WithField("code", push.Code).Debug("收到错误码")
|
||||
} else {
|
||||
logrus.WithField("methodName", methodName).Debug("收到推送")
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (cli *WsCli) SetReq(data []byte, flag bool) {
|
||||
cli.flag = flag
|
||||
if flag {
|
||||
cli.reqData = data
|
||||
}
|
||||
cli.reqDatas.Add(data)
|
||||
}
|
||||
|
||||
func (cli *WsCli) BuildReq() lib.RawReq {
|
||||
id := time.Now().UnixNano()
|
||||
var (
|
||||
data []byte
|
||||
err error
|
||||
)
|
||||
|
||||
data, err = cli.reqDatas.Pop()
|
||||
if err != nil {
|
||||
if cli.flag {
|
||||
data = cli.reqData
|
||||
} else {
|
||||
return lib.RawReq{}
|
||||
}
|
||||
}
|
||||
|
||||
rawReq := lib.RawReq{ID: id, Req: data}
|
||||
return rawReq
|
||||
}
|
||||
|
||||
func (cli *WsCli) Call(req []byte) ([]byte, error) {
|
||||
msg := &pb.UserMessage{}
|
||||
if err := proto.Unmarshal(req, msg); err != nil {
|
||||
logrus.Error("结果解析失败")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base64Str := msg.Sec
|
||||
dec, err := base64.StdEncoding.DecodeString(base64Str[35:])
|
||||
if err != nil {
|
||||
log.Errorf("base64 decode err %v", err)
|
||||
return nil, err
|
||||
}
|
||||
jsonRet := gjson.Parse(string(dec))
|
||||
|
||||
account := jsonRet.Get("account").String()
|
||||
|
||||
dialer := &websocket.Dialer{
|
||||
HandshakeTimeout: 2 * time.Second,
|
||||
}
|
||||
var conn *websocket.Conn
|
||||
if c, ok := cli.conns.Load(account); ok {
|
||||
conn = c.(*websocket.Conn)
|
||||
} else {
|
||||
conn, _, err = dialer.Dial(cli.addr, nil)
|
||||
if err != nil {
|
||||
logrus.Errorf("websocket conn err:%v", err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if msg.MainType == "user" && msg.SubType == "login" {
|
||||
cli.conns.Store(account, conn)
|
||||
}
|
||||
|
||||
// 向连接写数据
|
||||
conn.WriteMessage(websocket.BinaryMessage, req)
|
||||
|
||||
// 读数据
|
||||
var res []byte
|
||||
for {
|
||||
_, data, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
logrus.Errorf("readMessage err:%v", err)
|
||||
break
|
||||
}
|
||||
|
||||
// if cli.checkResp(data) {
|
||||
// return data, nil
|
||||
// } else {
|
||||
if !cli.checkPush(data) {
|
||||
return data, nil
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (cli *WsCli) Check(req lib.RawReq, resp lib.RawResp) *lib.CallResult {
|
||||
var result lib.CallResult
|
||||
result.Id = resp.ID
|
||||
result.Req = req
|
||||
result.Resp = resp
|
||||
|
||||
msg := &pb.UserMessage{}
|
||||
if err := proto.Unmarshal(resp.Resp, msg); err != nil {
|
||||
logrus.Error("结果解析失败")
|
||||
return &result
|
||||
}
|
||||
// logrus.WithFields(logrus.Fields{"msg": msg}).Debug("检查结果")
|
||||
return &result
|
||||
}
|
12
cmd/v2/theme/bundled.go
Normal file
12
cmd/v2/theme/bundled.go
Normal file
File diff suppressed because one or more lines are too long
33
cmd/v2/theme/icon.go
Normal file
33
cmd/v2/theme/icon.go
Normal file
File diff suppressed because one or more lines are too long
BIN
cmd/v2/theme/icon/excel.jpg
Normal file
BIN
cmd/v2/theme/icon/excel.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.6 KiB |
BIN
cmd/v2/theme/icon/mongodb.jpg
Normal file
BIN
cmd/v2/theme/icon/mongodb.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
12
cmd/v2/theme/image.go
Normal file
12
cmd/v2/theme/image.go
Normal file
File diff suppressed because one or more lines are too long
29
cmd/v2/theme/mytheme.go
Normal file
29
cmd/v2/theme/mytheme.go
Normal file
@ -0,0 +1,29 @@
|
||||
package theme
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
)
|
||||
|
||||
type MyTheme struct{}
|
||||
|
||||
var _ fyne.Theme = (*MyTheme)(nil)
|
||||
|
||||
// return bundled font resource
|
||||
// ResourceSourceHanSansTtf 即是 bundle.go 文件中 var 的变量名
|
||||
func (m MyTheme) Font(s fyne.TextStyle) fyne.Resource {
|
||||
return resourceMsyhTtc
|
||||
}
|
||||
func (*MyTheme) Color(n fyne.ThemeColorName, v fyne.ThemeVariant) color.Color {
|
||||
return theme.DarkTheme().Color(n, v)
|
||||
}
|
||||
|
||||
func (*MyTheme) Icon(n fyne.ThemeIconName) fyne.Resource {
|
||||
return theme.DarkTheme().Icon(n)
|
||||
}
|
||||
|
||||
func (*MyTheme) Size(n fyne.ThemeSizeName) float32 {
|
||||
return theme.DarkTheme().Size(n)
|
||||
}
|
698
cmd/v2/tpl.txt
Normal file
698
cmd/v2/tpl.txt
Normal file
@ -0,0 +1,698 @@
|
||||
reqDataMap := map[int32]TaskCondi{
|
||||
|
||||
101:{ 1,[]int32{ 25001,0,0,0,0 },
|
||||
|
||||
102:{ 2,[]int32{ 3,0,0,0,0 },
|
||||
|
||||
103:{ 3,[]int32{ 2,0,0,0,0 },
|
||||
|
||||
104:{ 4,[]int32{ 14007,10,0,0,0 },
|
||||
|
||||
105:{ 5,[]int32{ 25001,2,0,0,0 },
|
||||
|
||||
106:{ 6,[]int32{ 25004,5,0,0,0 },
|
||||
|
||||
107:{ 7,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
108:{ 8,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
109:{ 9,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
110:{ 10,[]int32{ 2,0,0,0,0 },
|
||||
|
||||
111:{ 11,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
112:{ 12,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
113:{ 13,[]int32{ 2,0,0,0,0 },
|
||||
|
||||
114:{ 14,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
115:{ 15,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
116:{ 16,[]int32{ 5,3,0,0,0 },
|
||||
|
||||
117:{ 17,[]int32{ 1,3,0,0,0 },
|
||||
|
||||
118:{ 18,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
119:{ 19,[]int32{ 2,0,0,0,0 },
|
||||
|
||||
120:{ 20,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
121:{ 21,[]int32{ 2,0,0,0,0 },
|
||||
|
||||
122:{ 22,[]int32{ 25001,0,0,0,0 },
|
||||
|
||||
123:{ 23,[]int32{ 3,5,20,0,0 },
|
||||
|
||||
124:{ 24,[]int32{ 4,0,0,0,0 },
|
||||
|
||||
125:{ 25,[]int32{ 3,25001,6,0,0 },
|
||||
|
||||
126:{ 26,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
127:{ 27,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
128:{ 28,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
129:{ 29,[]int32{ 2,22,25004,0,0 },
|
||||
|
||||
130:{ 30,[]int32{ 5,3,0,0,0 },
|
||||
|
||||
131:{ 31,[]int32{ 4,3,0,0,0 },
|
||||
|
||||
132:{ 32,[]int32{ 3,3,20,0,0 },
|
||||
|
||||
133:{ 33,[]int32{ 3,3,23,0,0 },
|
||||
|
||||
134:{ 34,[]int32{ 5,2,0,0,0 },
|
||||
|
||||
135:{ 35,[]int32{ 2,25001,0,0,0 },
|
||||
|
||||
136:{ 36,[]int32{ 1,3,3,1,2 },
|
||||
|
||||
137:{ 37,[]int32{ 1,3,0,0,0 },
|
||||
|
||||
138:{ 38,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
139:{ 39,[]int32{ 2,0,0,0,0 },
|
||||
|
||||
140:{ 40,[]int32{ 2,2,0,0,0 },
|
||||
|
||||
141:{ 41,[]int32{ 2,2,1,0,0 },
|
||||
|
||||
142:{ 42,[]int32{ 2,2,2,0,0 },
|
||||
|
||||
143:{ 43,[]int32{ 2,2,0,0,0 },
|
||||
|
||||
144:{ 44,[]int32{ 3,0,0,0,0 },
|
||||
|
||||
145:{ 45,[]int32{ 2,1,1,2,0 },
|
||||
|
||||
146:{ 46,[]int32{ 1,4,1,0,0 },
|
||||
|
||||
147:{ 47,[]int32{ 2,0,0,0,0 },
|
||||
|
||||
148:{ 48,[]int32{ 1,1,2,0,0 },
|
||||
|
||||
149:{ 49,[]int32{ 1,1,2,0,0 },
|
||||
|
||||
150:{ 50,[]int32{ 1,1,0,0,0 },
|
||||
|
||||
151:{ 51,[]int32{ 1,1,0,0,0 },
|
||||
|
||||
152:{ 52,[]int32{ 1,14007,0,0,0 },
|
||||
|
||||
153:{ 53,[]int32{ 2,0,0,0,0 },
|
||||
|
||||
154:{ 54,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
155:{ 55,[]int32{ 2,3,0,0,0 },
|
||||
|
||||
156:{ 56,[]int32{ 1,1,2,0,0 },
|
||||
|
||||
157:{ 57,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
158:{ 58,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
159:{ 59,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
160:{ 60,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
161:{ 61,[]int32{ 109,0,0,0,0 },
|
||||
|
||||
162:{ 62,[]int32{ 2,0,0,0,0 },
|
||||
|
||||
163:{ 63,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
164:{ 64,[]int32{ 2,0,0,0,0 },
|
||||
|
||||
165:{ 65,[]int32{ 2,10001,0,0,0 },
|
||||
|
||||
166:{ 66,[]int32{ 2,1,0,0,0 },
|
||||
|
||||
167:{ 67,[]int32{ 1000,1,0,0,0 },
|
||||
|
||||
168:{ 68,[]int32{ 1000,1,0,0,0 },
|
||||
|
||||
169:{ 69,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
170:{ 1,[]int32{ 44006,0,0,0,0 },
|
||||
|
||||
171:{ 70,[]int32{ 1,101,0,0,0 },
|
||||
|
||||
172:{ 18,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
173:{ 71,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
174:{ 70,[]int32{ 1,101,0,0,0 },
|
||||
|
||||
175:{ 70,[]int32{ 1,102,0,0,0 },
|
||||
|
||||
176:{ 70,[]int32{ 1,103,0,0,0 },
|
||||
|
||||
177:{ 70,[]int32{ 1,104,0,0,0 },
|
||||
|
||||
178:{ 70,[]int32{ 1,105,0,0,0 },
|
||||
|
||||
179:{ 70,[]int32{ 1,106,0,0,0 },
|
||||
|
||||
180:{ 70,[]int32{ 1,107,0,0,0 },
|
||||
|
||||
181:{ 70,[]int32{ 1,108,0,0,0 },
|
||||
|
||||
182:{ 70,[]int32{ 1,109,0,0,0 },
|
||||
|
||||
183:{ 140,[]int32{ 1,10001,0,0,0 },
|
||||
|
||||
184:{ 140,[]int32{ 1,10002,0,0,0 },
|
||||
|
||||
185:{ 140,[]int32{ 1,10003,0,0,0 },
|
||||
|
||||
186:{ 140,[]int32{ 1,10004,0,0,0 },
|
||||
|
||||
187:{ 109,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
188:{ 104,[]int32{ 100,0,0,0,0 },
|
||||
|
||||
189:{ 70,[]int32{ 1,110,0,0,0 },
|
||||
|
||||
190:{ 70,[]int32{ 1,111,1,1,1 },
|
||||
|
||||
191:{ 70,[]int32{ 1,112,2,2,2 },
|
||||
|
||||
192:{ 70,[]int32{ 1,113,3,3,3 },
|
||||
|
||||
193:{ 70,[]int32{ 1,114,4,4,4 },
|
||||
|
||||
194:{ 138,[]int32{ 30,0,0,0,0 },
|
||||
|
||||
195:{ 140,[]int32{ 1,10005,0,0,0 },
|
||||
|
||||
196:{ 140,[]int32{ 1,10006,0,0,0 },
|
||||
|
||||
197:{ 140,[]int32{ 1,10007,0,0,0 },
|
||||
|
||||
198:{ 140,[]int32{ 1,10008,0,0,0 },
|
||||
|
||||
199:{ 140,[]int32{ 1,10009,0,0,0 },
|
||||
|
||||
200:{ 140,[]int32{ 1,10010,0,0,0 },
|
||||
|
||||
10001:{ 24,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
10002:{ 24,[]int32{ 5,0,0,0,0 },
|
||||
|
||||
10003:{ 24,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
10004:{ 24,[]int32{ 20,0,0,0,0 },
|
||||
|
||||
10005:{ 24,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
10006:{ 24,[]int32{ 100,0,0,0,0 },
|
||||
|
||||
10007:{ 24,[]int32{ 200,0,0,0,0 },
|
||||
|
||||
10008:{ 24,[]int32{ 300,0,0,0,0 },
|
||||
|
||||
10009:{ 24,[]int32{ 500,0,0,0,0 },
|
||||
|
||||
10010:{ 24,[]int32{ 1000,0,0,0,0 },
|
||||
|
||||
10101:{ 7,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
10201:{ 18,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
10202:{ 18,[]int32{ 5,0,0,0,0 },
|
||||
|
||||
10203:{ 18,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
10204:{ 18,[]int32{ 20,0,0,0,0 },
|
||||
|
||||
10205:{ 18,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
10206:{ 18,[]int32{ 100,0,0,0,0 },
|
||||
|
||||
10207:{ 18,[]int32{ 200,0,0,0,0 },
|
||||
|
||||
10208:{ 18,[]int32{ 300,0,0,0,0 },
|
||||
|
||||
10209:{ 18,[]int32{ 500,0,0,0,0 },
|
||||
|
||||
10210:{ 18,[]int32{ 1000,0,0,0,0 },
|
||||
|
||||
10301:{ 18,[]int32{ 1,5,0,0,0 },
|
||||
|
||||
10302:{ 50,[]int32{ 5,5,0,0,0 },
|
||||
|
||||
10303:{ 50,[]int32{ 10,5,0,0,0 },
|
||||
|
||||
10304:{ 50,[]int32{ 20,5,0,0,0 },
|
||||
|
||||
10305:{ 50,[]int32{ 50,5,0,0,0 },
|
||||
|
||||
10306:{ 50,[]int32{ 100,5,0,0,0 },
|
||||
|
||||
10307:{ 50,[]int32{ 200,5,0,0,0 },
|
||||
|
||||
10308:{ 50,[]int32{ 300,5,0,0,0 },
|
||||
|
||||
10309:{ 50,[]int32{ 500,5,0,0,0 },
|
||||
|
||||
10310:{ 50,[]int32{ 1000,5,0,0,0 },
|
||||
|
||||
10401:{ 50,[]int32{ 1,6,0,0,0 },
|
||||
|
||||
10402:{ 50,[]int32{ 5,6,0,0,0 },
|
||||
|
||||
10403:{ 50,[]int32{ 10,6,0,0,0 },
|
||||
|
||||
10404:{ 50,[]int32{ 20,6,0,0,0 },
|
||||
|
||||
10405:{ 50,[]int32{ 50,6,0,0,0 },
|
||||
|
||||
10406:{ 50,[]int32{ 100,6,0,0,0 },
|
||||
|
||||
10407:{ 50,[]int32{ 200,6,0,0,0 },
|
||||
|
||||
10408:{ 50,[]int32{ 300,6,0,0,0 },
|
||||
|
||||
10409:{ 50,[]int32{ 500,6,0,0,0 },
|
||||
|
||||
10410:{ 50,[]int32{ 1000,6,0,0,0 },
|
||||
|
||||
10501:{ 58,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
10502:{ 58,[]int32{ 5,0,0,0,0 },
|
||||
|
||||
10503:{ 58,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
10504:{ 58,[]int32{ 20,0,0,0,0 },
|
||||
|
||||
10505:{ 58,[]int32{ 30,0,0,0,0 },
|
||||
|
||||
10506:{ 58,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
10507:{ 58,[]int32{ 70,0,0,0,0 },
|
||||
|
||||
10508:{ 58,[]int32{ 100,0,0,0,0 },
|
||||
|
||||
10601:{ 62,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
10602:{ 62,[]int32{ 5,0,0,0,0 },
|
||||
|
||||
10603:{ 62,[]int32{ 99,0,0,0,0 },
|
||||
|
||||
10701:{ 64,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
10702:{ 64,[]int32{ 5,0,0,0,0 },
|
||||
|
||||
10703:{ 64,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
10704:{ 64,[]int32{ 20,0,0,0,0 },
|
||||
|
||||
10705:{ 64,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
10706:{ 64,[]int32{ 100,0,0,0,0 },
|
||||
|
||||
10707:{ 64,[]int32{ 200,0,0,0,0 },
|
||||
|
||||
10708:{ 64,[]int32{ 300,0,0,0,0 },
|
||||
|
||||
10709:{ 64,[]int32{ 500,0,0,0,0 },
|
||||
|
||||
10710:{ 64,[]int32{ 1000,0,0,0,0 },
|
||||
|
||||
10801:{ 8,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
10802:{ 8,[]int32{ 5,0,0,0,0 },
|
||||
|
||||
10803:{ 8,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
10804:{ 8,[]int32{ 20,0,0,0,0 },
|
||||
|
||||
10805:{ 8,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
10806:{ 8,[]int32{ 100,0,0,0,0 },
|
||||
|
||||
10807:{ 8,[]int32{ 200,0,0,0,0 },
|
||||
|
||||
10808:{ 8,[]int32{ 300,0,0,0,0 },
|
||||
|
||||
10809:{ 8,[]int32{ 500,0,0,0,0 },
|
||||
|
||||
10810:{ 18,[]int32{ 1000,0,0,0,0 },
|
||||
|
||||
2008001:{ 8,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
2012001:{ 12,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
2018001:{ 18,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
2024001:{ 24,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
2047001:{ 47,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
2062001:{ 62,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
2064001:{ 64,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
2130001:{ 130,[]int32{ 3,0,0,0,0 },
|
||||
|
||||
3008001:{ 8,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
3012001:{ 12,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
3018001:{ 18,[]int32{ 5,0,0,0,0 },
|
||||
|
||||
3024001:{ 24,[]int32{ 5,0,0,0,0 },
|
||||
|
||||
3047001:{ 47,[]int32{ 7,0,0,0,0 },
|
||||
|
||||
3061001:{ 62,[]int32{ 7,0,0,0,0 },
|
||||
|
||||
3064001:{ 64,[]int32{ 7,0,0,0,0 },
|
||||
|
||||
3088001:{ 88,[]int32{ 3,0,0,0,0 },
|
||||
|
||||
3104001:{ 104,[]int32{ 1000,0,0,0,0 },
|
||||
|
||||
3105001:{ 105,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
3130001:{ 130,[]int32{ 30,0,0,0,0 },
|
||||
|
||||
4008001:{ 8,[]int32{ 3,0,0,0,0 },
|
||||
|
||||
4008002:{ 8,[]int32{ 7,0,0,0,0 },
|
||||
|
||||
4008003:{ 8,[]int32{ 30,0,0,0,0 },
|
||||
|
||||
4008004:{ 8,[]int32{ 90,0,0,0,0 },
|
||||
|
||||
4008005:{ 8,[]int32{ 180,0,0,0,0 },
|
||||
|
||||
4008006:{ 8,[]int32{ 365,0,0,0,0 },
|
||||
|
||||
4008007:{ 9,[]int32{ 3,0,0,0,0 },
|
||||
|
||||
4008008:{ 9,[]int32{ 7,0,0,0,0 },
|
||||
|
||||
4008009:{ 9,[]int32{ 14,0,0,0,0 },
|
||||
|
||||
4008010:{ 9,[]int32{ 30,0,0,0,0 },
|
||||
|
||||
4010001:{ 10,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
4010002:{ 10,[]int32{ 5,0,0,0,0 },
|
||||
|
||||
4010003:{ 10,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
4010004:{ 10,[]int32{ 20,0,0,0,0 },
|
||||
|
||||
4010005:{ 10,[]int32{ 30,0,0,0,0 },
|
||||
|
||||
4010006:{ 10,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
4011001:{ 11,[]int32{ 5,0,0,0,0 },
|
||||
|
||||
4011002:{ 11,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
4011003:{ 11,[]int32{ 30,0,0,0,0 },
|
||||
|
||||
4011004:{ 11,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
4011005:{ 11,[]int32{ 100,0,0,0,0 },
|
||||
|
||||
4011006:{ 11,[]int32{ 300,0,0,0,0 },
|
||||
|
||||
4011007:{ 11,[]int32{ 500,0,0,0,0 },
|
||||
|
||||
4011008:{ 11,[]int32{ 1000,0,0,0,0 },
|
||||
|
||||
4011009:{ 11,[]int32{ 3000,0,0,0,0 },
|
||||
|
||||
4011010:{ 11,[]int32{ 5000,0,0,0,0 },
|
||||
|
||||
4011011:{ 11,[]int32{ 10000,0,0,0,0 },
|
||||
|
||||
4012001:{ 12,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
4012002:{ 12,[]int32{ 5,0,0,0,0 },
|
||||
|
||||
4012003:{ 12,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
4012004:{ 12,[]int32{ 30,0,0,0,0 },
|
||||
|
||||
4012005:{ 12,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
4012006:{ 12,[]int32{ 100,0,0,0,0 },
|
||||
|
||||
4012007:{ 12,[]int32{ 300,0,0,0,0 },
|
||||
|
||||
4012008:{ 12,[]int32{ 500,0,0,0,0 },
|
||||
|
||||
4012009:{ 12,[]int32{ 1000,0,0,0,0 },
|
||||
|
||||
4016001:{ 16,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
4016002:{ 16,[]int32{ 2,0,0,0,0 },
|
||||
|
||||
4016003:{ 16,[]int32{ 3,0,0,0,0 },
|
||||
|
||||
4016004:{ 16,[]int32{ 5,0,0,0,0 },
|
||||
|
||||
4016005:{ 16,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
4016006:{ 16,[]int32{ 15,0,0,0,0 },
|
||||
|
||||
4016007:{ 16,[]int32{ 20,0,0,0,0 },
|
||||
|
||||
4016008:{ 16,[]int32{ 30,0,0,0,0 },
|
||||
|
||||
4016009:{ 16,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
4018001:{ 18,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
4018002:{ 18,[]int32{ 20,0,0,0,0 },
|
||||
|
||||
4018003:{ 18,[]int32{ 30,0,0,0,0 },
|
||||
|
||||
4018004:{ 18,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
4018005:{ 18,[]int32{ 100,0,0,0,0 },
|
||||
|
||||
4018006:{ 18,[]int32{ 200,0,0,0,0 },
|
||||
|
||||
4018007:{ 18,[]int32{ 300,0,0,0,0 },
|
||||
|
||||
4018008:{ 18,[]int32{ 500,0,0,0,0 },
|
||||
|
||||
4018009:{ 18,[]int32{ 1000,0,0,0,0 },
|
||||
|
||||
4018010:{ 18,[]int32{ 2000,0,0,0,0 },
|
||||
|
||||
4018011:{ 18,[]int32{ 5000,0,0,0,0 },
|
||||
|
||||
4018012:{ 18,[]int32{ 10000,0,0,0,0 },
|
||||
|
||||
4020001:{ 20,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
4020002:{ 20,[]int32{ 20,0,0,0,0 },
|
||||
|
||||
4020003:{ 20,[]int32{ 30,0,0,0,0 },
|
||||
|
||||
4020004:{ 20,[]int32{ 40,0,0,0,0 },
|
||||
|
||||
4020005:{ 20,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
4020006:{ 20,[]int32{ 60,0,0,0,0 },
|
||||
|
||||
4043001:{ 43,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
4043002:{ 43,[]int32{ 2,0,0,0,0 },
|
||||
|
||||
4043003:{ 43,[]int32{ 4,0,0,0,0 },
|
||||
|
||||
4043004:{ 43,[]int32{ 6,0,0,0,0 },
|
||||
|
||||
4043005:{ 43,[]int32{ 12,0,0,0,0 },
|
||||
|
||||
4043006:{ 43,[]int32{ 18,0,0,0,0 },
|
||||
|
||||
4043007:{ 43,[]int32{ 24,0,0,0,0 },
|
||||
|
||||
4043008:{ 43,[]int32{ 30,0,0,0,0 },
|
||||
|
||||
4043009:{ 43,[]int32{ 60,0,0,0,0 },
|
||||
|
||||
4043010:{ 43,[]int32{ 120,0,0,0,0 },
|
||||
|
||||
4047001:{ 47,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
4047002:{ 47,[]int32{ 20,0,0,0,0 },
|
||||
|
||||
4047003:{ 47,[]int32{ 30,0,0,0,0 },
|
||||
|
||||
4047004:{ 47,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
4047005:{ 47,[]int32{ 100,0,0,0,0 },
|
||||
|
||||
4047006:{ 47,[]int32{ 200,0,0,0,0 },
|
||||
|
||||
4047007:{ 47,[]int32{ 300,0,0,0,0 },
|
||||
|
||||
4047008:{ 47,[]int32{ 500,0,0,0,0 },
|
||||
|
||||
4047009:{ 47,[]int32{ 1000,0,0,0,0 },
|
||||
|
||||
4047010:{ 47,[]int32{ 2000,0,0,0,0 },
|
||||
|
||||
4047011:{ 47,[]int32{ 3000,0,0,0,0 },
|
||||
|
||||
4047012:{ 47,[]int32{ 5000,0,0,0,0 },
|
||||
|
||||
4047013:{ 47,[]int32{ 10000,0,0,0,0 },
|
||||
|
||||
4064001:{ 64,[]int32{ 5,0,0,0,0 },
|
||||
|
||||
4064002:{ 64,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
4064003:{ 64,[]int32{ 20,0,0,0,0 },
|
||||
|
||||
4064004:{ 64,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
4064005:{ 64,[]int32{ 100,0,0,0,0 },
|
||||
|
||||
4064006:{ 64,[]int32{ 200,0,0,0,0 },
|
||||
|
||||
4064007:{ 64,[]int32{ 500,0,0,0,0 },
|
||||
|
||||
4068001:{ 68,[]int32{ 50000,0,0,0,0 },
|
||||
|
||||
4068002:{ 68,[]int32{ 500000,0,0,0,0 },
|
||||
|
||||
4068003:{ 68,[]int32{ 5000000,0,0,0,0 },
|
||||
|
||||
4068004:{ 68,[]int32{ 50000000,0,0,0,0 },
|
||||
|
||||
4084001:{ 84,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
4084002:{ 84,[]int32{ 20,0,0,0,0 },
|
||||
|
||||
4084003:{ 84,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
4084004:{ 84,[]int32{ 100,0,0,0,0 },
|
||||
|
||||
4085001:{ 85,[]int32{ 5,0,0,0,0 },
|
||||
|
||||
4085002:{ 85,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
4085003:{ 85,[]int32{ 20,0,0,0,0 },
|
||||
|
||||
4085004:{ 85,[]int32{ 30,0,0,0,0 },
|
||||
|
||||
4085005:{ 85,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
4096001:{ 96,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
4096002:{ 96,[]int32{ 20,0,0,0,0 },
|
||||
|
||||
4096003:{ 96,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
4096004:{ 96,[]int32{ 100,0,0,0,0 },
|
||||
|
||||
4096005:{ 96,[]int32{ 200,0,0,0,0 },
|
||||
|
||||
4096006:{ 96,[]int32{ 300,0,0,0,0 },
|
||||
|
||||
4096007:{ 96,[]int32{ 500,0,0,0,0 },
|
||||
|
||||
4096008:{ 96,[]int32{ 1000,0,0,0,0 },
|
||||
|
||||
4096009:{ 96,[]int32{ 2000,0,0,0,0 },
|
||||
|
||||
4096010:{ 96,[]int32{ 3000,0,0,0,0 },
|
||||
|
||||
4096011:{ 96,[]int32{ 5000,0,0,0,0 },
|
||||
|
||||
4096012:{ 96,[]int32{ 10000,0,0,0,0 },
|
||||
|
||||
4104001:{ 104,[]int32{ 500,0,0,0,0 },
|
||||
|
||||
4104002:{ 104,[]int32{ 1000,0,0,0,0 },
|
||||
|
||||
4104003:{ 104,[]int32{ 3000,0,0,0,0 },
|
||||
|
||||
4104004:{ 104,[]int32{ 5000,0,0,0,0 },
|
||||
|
||||
4104005:{ 104,[]int32{ 10000,0,0,0,0 },
|
||||
|
||||
4104006:{ 104,[]int32{ 20000,0,0,0,0 },
|
||||
|
||||
4104007:{ 104,[]int32{ 30000,0,0,0,0 },
|
||||
|
||||
4104008:{ 104,[]int32{ 50000,0,0,0,0 },
|
||||
|
||||
4104009:{ 104,[]int32{ 100000,0,0,0,0 },
|
||||
|
||||
4104010:{ 104,[]int32{ 200000,0,0,0,0 },
|
||||
|
||||
4104011:{ 104,[]int32{ 500000,0,0,0,0 },
|
||||
|
||||
4128001:{ 128,[]int32{ 1100,0,0,0,0 },
|
||||
|
||||
4128002:{ 128,[]int32{ 1200,0,0,0,0 },
|
||||
|
||||
4128003:{ 128,[]int32{ 1300,0,0,0,0 },
|
||||
|
||||
4128004:{ 128,[]int32{ 1400,0,0,0,0 },
|
||||
|
||||
4128005:{ 128,[]int32{ 1500,0,0,0,0 },
|
||||
|
||||
4128006:{ 128,[]int32{ 1600,0,0,0,0 },
|
||||
|
||||
4128007:{ 128,[]int32{ 1700,0,0,0,0 },
|
||||
|
||||
4128008:{ 128,[]int32{ 1800,0,0,0,0 },
|
||||
|
||||
4128009:{ 128,[]int32{ 1900,0,0,0,0 },
|
||||
|
||||
4128010:{ 128,[]int32{ 2000,0,0,0,0 },
|
||||
|
||||
4131001:{ 131,[]int32{ 5,0,0,0,0 },
|
||||
|
||||
4131002:{ 131,[]int32{ 10,0,0,0,0 },
|
||||
|
||||
4131003:{ 131,[]int32{ 20,0,0,0,0 },
|
||||
|
||||
4131004:{ 131,[]int32{ 30,0,0,0,0 },
|
||||
|
||||
4131005:{ 131,[]int32{ 50,0,0,0,0 },
|
||||
|
||||
4131006:{ 131,[]int32{ 100,0,0,0,0 },
|
||||
|
||||
4131007:{ 131,[]int32{ 200,0,0,0,0 },
|
||||
|
||||
4131008:{ 131,[]int32{ 300,0,0,0,0 },
|
||||
|
||||
4131009:{ 131,[]int32{ 500,0,0,0,0 },
|
||||
|
||||
4131010:{ 131,[]int32{ 1000,0,0,0,0 },
|
||||
|
||||
5011001:{ 11,[]int32{ 3,0,0,0,0 },
|
||||
|
||||
5012001:{ 12,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
5018001:{ 18,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
5024001:{ 24,[]int32{ 1,0,0,0,0 },
|
||||
|
||||
5047001:{ 47,[]int32{ 6,0,0,0,0 },
|
||||
|
||||
5063001:{ 63,[]int32{ 100,0,0,0,0 },
|
||||
|
||||
5068001:{ 68,[]int32{ 200000,0,0,0,0 },
|
||||
|
||||
5104001:{ 104,[]int32{ 100,0,0,0,0 },
|
||||
}
|
35
cmd/v2/ui/about.go
Normal file
35
cmd/v2/ui/about.go
Normal file
@ -0,0 +1,35 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"net/url"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type about struct {
|
||||
aboutDialog dialog.Dialog
|
||||
}
|
||||
|
||||
func newAbout() *about {
|
||||
var a about
|
||||
ver := toolWin.app.Metadata().Version
|
||||
link, _ := url.Parse("http://10.0.0.9:8080")
|
||||
wlink := widget.NewHyperlinkWithStyle("更新包", link, fyne.TextAlignLeading, fyne.TextStyle{})
|
||||
content := widget.NewCard("", "", widget.NewRichTextFromMarkdown(
|
||||
`
|
||||
梦工厂项目辅助工具GUI
|
||||
@v`+ver,
|
||||
))
|
||||
a.aboutDialog = dialog.NewCustom(common.APP_ABOUT_TITLE, common.APP_ABOUT_CONFIRM,
|
||||
container.NewVBox(content, wlink), toolWin.w)
|
||||
|
||||
return &a
|
||||
}
|
||||
|
||||
func showAbout() {
|
||||
newAbout().aboutDialog.Show()
|
||||
}
|
84
cmd/v2/ui/app_auto.go
Normal file
84
cmd/v2/ui/app_auto.go
Normal file
@ -0,0 +1,84 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/cmd/v2/service"
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/driver/desktop"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
//半自动化 依据采集的数据
|
||||
type appAuto struct {
|
||||
appAdapter
|
||||
|
||||
obs observer.Observer
|
||||
|
||||
caseList func()
|
||||
itemList *common.ItemList
|
||||
}
|
||||
|
||||
// 读文件
|
||||
func (app *appAuto) loadData() error {
|
||||
bytes, err := ioutil.ReadFile(filepath.Join(".", "robot.log"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Debug(bytes)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (app *appAuto) LazyInit(service service.PttService, obs observer.Observer) error {
|
||||
app.obs = obs
|
||||
app.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_AUTO, theme.StorageIcon(), nil)
|
||||
|
||||
content := container.NewMax()
|
||||
content.Objects = []fyne.CanvasObject{}
|
||||
|
||||
// 初始化列表
|
||||
app.itemList = common.NewItemList()
|
||||
app.itemList.ItemList = app.itemList.CreateList()
|
||||
|
||||
// 读取采集的数据文件
|
||||
app.caseList = func() {
|
||||
app.loadData()
|
||||
}
|
||||
|
||||
defer func() {
|
||||
app.caseList()
|
||||
}()
|
||||
|
||||
// layout
|
||||
// panel := container.NewVSplit(container.NewBorder(app.monitorHeader, nil, nil, nil, app.monitorList), resPanel)
|
||||
// panel.Offset = 0.8
|
||||
content.Objects = append(content.Objects)
|
||||
app.tabItem.Content = content
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *appAuto) OpenDefault() string {
|
||||
return common.TOOLBAR_AUTO
|
||||
}
|
||||
|
||||
func (a *appAuto) GetAppName() string {
|
||||
return "自动化"
|
||||
}
|
||||
|
||||
func (a appAuto) OnClose() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (this *appAuto) ShortCut() fyne.Shortcut {
|
||||
return &desktop.CustomShortcut{KeyName: fyne.Key3, Modifier: desktop.AltModifier}
|
||||
}
|
||||
|
||||
func (this *appAuto) Icon() fyne.Resource {
|
||||
return theme.StorageIcon()
|
||||
}
|
112
cmd/v2/ui/app_container.go
Normal file
112
cmd/v2/ui/app_container.go
Normal file
@ -0,0 +1,112 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/service"
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
|
||||
"fyne.io/fyne/v2/container"
|
||||
)
|
||||
|
||||
type appContainer struct {
|
||||
appStatusMap map[string]appStatus
|
||||
container.DocTabs
|
||||
obs observer.Observer
|
||||
ai []appInterface
|
||||
service service.PttService
|
||||
}
|
||||
|
||||
func newAppContainer(ai []appInterface, service service.PttService, obs observer.Observer) *appContainer {
|
||||
at := &appContainer{ai: ai, service: service, obs: obs}
|
||||
|
||||
at.appStatusMap = make(map[string]appStatus)
|
||||
at.CloseIntercept = at.closeHandle
|
||||
at.SetTabLocation(container.TabLocationTop)
|
||||
at.ExtendBaseWidget(at)
|
||||
at.OnSelected = func(item *container.TabItem) {
|
||||
item.Content.Refresh()
|
||||
}
|
||||
return at
|
||||
}
|
||||
|
||||
type appStatus struct {
|
||||
lazyInit bool
|
||||
}
|
||||
|
||||
func (at *appContainer) closeHandle(tab *container.TabItem) {
|
||||
for _, app := range at.ai {
|
||||
if app.GetAppName() == tab.Text {
|
||||
if app.OnClose() {
|
||||
at.Remove(tab)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (at *appContainer) openApp(app appInterface) error {
|
||||
for _, appItem := range at.Items {
|
||||
if appItem.Text == app.GetAppName() {
|
||||
at.Select(appItem)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err := at.initApp(app)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tab := app.GetTabItem()
|
||||
at.Append(tab)
|
||||
at.Select(tab)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (at *appContainer) openWelcome() (string, error) {
|
||||
var firstTab *container.TabItem
|
||||
app := &appWelcome{}
|
||||
if err := at.initApp(app); err != nil {
|
||||
return app.GetAppName(), err
|
||||
}
|
||||
tab := app.GetTabItem()
|
||||
at.Append(tab)
|
||||
if firstTab == nil {
|
||||
firstTab = tab
|
||||
}
|
||||
if firstTab != nil {
|
||||
at.Select(firstTab)
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// open default app
|
||||
func (at *appContainer) openDefaultApp(appName string) (string, error) {
|
||||
var firstTab *container.TabItem
|
||||
for _, app := range at.ai {
|
||||
if app.OpenDefault() == appName {
|
||||
if err := at.initApp(app); err != nil {
|
||||
return app.GetAppName(), err
|
||||
}
|
||||
tab := app.GetTabItem()
|
||||
at.Append(tab)
|
||||
if firstTab == nil {
|
||||
firstTab = tab
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if firstTab != nil {
|
||||
at.Select(firstTab)
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (at *appContainer) initApp(app appInterface) error {
|
||||
st, ok := at.appStatusMap[app.GetAppName()]
|
||||
if !ok || !st.lazyInit {
|
||||
err := app.LazyInit(at.service, at.obs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
at.appStatusMap[app.GetAppName()] = appStatus{lazyInit: true}
|
||||
}
|
||||
return nil
|
||||
}
|
72
cmd/v2/ui/app_interface.go
Normal file
72
cmd/v2/ui/app_interface.go
Normal file
@ -0,0 +1,72 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/service"
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
)
|
||||
|
||||
type appInterface interface {
|
||||
LazyInit(service service.PttService, obs observer.Observer) error
|
||||
GetTabItem() *container.TabItem
|
||||
GetAppName() string
|
||||
OpenDefault() string
|
||||
GetUI() interface{}
|
||||
OnClose() bool
|
||||
Icon() fyne.Resource
|
||||
}
|
||||
|
||||
var (
|
||||
appRegister = []appInterface{
|
||||
&appMonitor{},
|
||||
&appTester{},
|
||||
// &appAuto{},
|
||||
}
|
||||
|
||||
toolRegister = []appInterface{
|
||||
// &appWelcome{},
|
||||
&appGen{},
|
||||
&appPbGen{},
|
||||
&appLock{},
|
||||
&appTerm{},
|
||||
&appPing{},
|
||||
&appMgo{},
|
||||
&appConfigValid{},
|
||||
}
|
||||
)
|
||||
|
||||
type appAdapter struct {
|
||||
tabItem *container.TabItem
|
||||
ai []appInterface
|
||||
}
|
||||
|
||||
func (a appAdapter) LazyInit() error {
|
||||
panic("implement LazyInit")
|
||||
}
|
||||
|
||||
func (a appAdapter) GetAppName() string {
|
||||
panic("implement GetAppName()")
|
||||
}
|
||||
|
||||
func (a appAdapter) GetUI() interface{} {
|
||||
panic("implement GetUI()")
|
||||
}
|
||||
|
||||
func (a appAdapter) OpenDefault() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (a appAdapter) GetTabItem() *container.TabItem {
|
||||
return a.tabItem
|
||||
}
|
||||
|
||||
func (a appAdapter) OnClose() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (a appAdapter) Icon() fyne.Resource {
|
||||
return theme.FyneLogo()
|
||||
}
|
110
cmd/v2/ui/app_monitor.go
Normal file
110
cmd/v2/ui/app_monitor.go
Normal file
@ -0,0 +1,110 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/cmd/v2/model"
|
||||
"go_dreamfactory/cmd/v2/service"
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/driver/desktop"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
)
|
||||
|
||||
type appMonitor struct {
|
||||
appAdapter
|
||||
|
||||
obs observer.Observer
|
||||
logPanel *widget.Entry
|
||||
monitorList *common.ItemList
|
||||
id int64
|
||||
}
|
||||
|
||||
func (app *appMonitor) LazyInit(service service.PttService, obs observer.Observer) error {
|
||||
app.obs = obs
|
||||
app.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_MONITOR, theme.MediaVideoIcon(), nil)
|
||||
|
||||
content := container.NewMax()
|
||||
content.Objects = []fyne.CanvasObject{}
|
||||
|
||||
// panel for output log
|
||||
app.logPanel = widget.NewMultiLineEntry()
|
||||
app.logPanel.Wrapping = fyne.TextWrapWord
|
||||
//clear button
|
||||
clearBtn := widget.NewButtonWithIcon(common.APP_TESTCASE_BTN_CLEARLOG, theme.DeleteIcon(), func() {
|
||||
app.logPanel.SetText("")
|
||||
app.monitorList.Reset()
|
||||
})
|
||||
|
||||
resPanel := container.NewBorder(container.NewHBox(clearBtn, layout.NewSpacer()), nil, nil, nil, app.logPanel)
|
||||
|
||||
app.monitorList = common.NewItemList()
|
||||
|
||||
app.monitorList.ItemList = app.monitorList.CreateList()
|
||||
app.monitorList.ItemList.OnSelected = func(id widget.ListItemID) {
|
||||
o := app.monitorList.CachedList.Items[id]
|
||||
pd, ok := o.Data.(*model.PushModel)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if res, err := anypb.New(pd.Msg.Data); err == nil {
|
||||
app.logPanel.Text = res.String()
|
||||
app.logPanel.Refresh()
|
||||
} else {
|
||||
logrus.WithField("err", err).Error("view detail")
|
||||
}
|
||||
}
|
||||
|
||||
// layout
|
||||
panel := container.NewVSplit(container.NewBorder(nil, nil, nil, nil,
|
||||
app.monitorList.ItemList), resPanel)
|
||||
panel.Offset = 0.8
|
||||
content.Objects = append(content.Objects, panel)
|
||||
app.tabItem.Content = content
|
||||
app.monitorlistener()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *appMonitor) OpenDefault() string {
|
||||
return common.TOOLBAR_MONITOR
|
||||
}
|
||||
|
||||
func (a *appMonitor) GetAppName() string {
|
||||
return common.TOOLBAR_MONITOR
|
||||
}
|
||||
|
||||
func (a appMonitor) OnClose() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// monitor list data
|
||||
func (app *appMonitor) monitorlistener() {
|
||||
app.obs.AddListener(observer.EVENT_APP_MONI, observer.Listener{
|
||||
OnNotify: func(d interface{}, args ...interface{}) {
|
||||
app.id++
|
||||
data := d.(*model.PushModel)
|
||||
protocol := fmt.Sprintf("【%s.%s】", data.Msg.MainType, data.Msg.SubType)
|
||||
app.monitorList.AddItem(common.Item{
|
||||
Text: fmt.Sprintf("%d - %-50v %-50v %-50v",
|
||||
app.id, protocol, data.MethodName, data.DataTime),
|
||||
Data: data,
|
||||
})
|
||||
|
||||
app.monitorList.ItemList.ScrollToBottom()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (this *appMonitor) ShortCut() fyne.Shortcut {
|
||||
return &desktop.CustomShortcut{KeyName: fyne.Key3, Modifier: desktop.AltModifier}
|
||||
}
|
||||
|
||||
func (this *appMonitor) Icon() fyne.Resource {
|
||||
return theme.MediaVideoIcon()
|
||||
}
|
187
cmd/v2/ui/app_testcase.go
Normal file
187
cmd/v2/ui/app_testcase.go
Normal file
@ -0,0 +1,187 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
pb2 "go_dreamfactory/cmd/v2/lib/pb"
|
||||
"go_dreamfactory/cmd/v2/model"
|
||||
"go_dreamfactory/cmd/v2/service"
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
"go_dreamfactory/pb"
|
||||
"time"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/driver/desktop"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type appTester struct {
|
||||
appAdapter
|
||||
progress *widget.ProgressBarInfinite
|
||||
}
|
||||
|
||||
func (a *appTester) GetAppName() string {
|
||||
return common.TOOLBAR_TESTER
|
||||
}
|
||||
|
||||
func (a *appTester) disEnabled(t *model.TestCase) bool {
|
||||
return !t.Enabled
|
||||
}
|
||||
|
||||
func (a *appTester) LazyInit(service service.PttService, obs observer.Observer) error {
|
||||
a.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_TESTER, theme.DocumentIcon(), nil)
|
||||
|
||||
a.progress = widget.NewProgressBarInfinite()
|
||||
a.progress.Hide()
|
||||
|
||||
content := container.NewMax()
|
||||
title := widget.NewLabel(common.APP_TESTCASE_TITLE)
|
||||
intro := widget.NewLabel("")
|
||||
intro.Wrapping = fyne.TextWrapWord
|
||||
caseContent := container.NewBorder(
|
||||
container.NewVBox(container.NewHBox(title), widget.NewSeparator(), intro), nil, nil, nil, content)
|
||||
|
||||
setNav := func(t *model.TestCase) {
|
||||
defer a.progress.Hide()
|
||||
viewKey := fmt.Sprintf("%s.%s", t.MainType, t.SubType)
|
||||
title.SetText(fmt.Sprintf("> %s", viewKey))
|
||||
intro.SetText(t.Desc)
|
||||
content.Objects = []fyne.CanvasObject{}
|
||||
|
||||
if view, ok := ViewRegister[viewKey]; ok {
|
||||
timeLbl := widget.NewLabel("time")
|
||||
resLog := widget.NewMultiLineEntry()
|
||||
view.Init(service, obs, globalWin.w, resLog)
|
||||
|
||||
obs.AddListener(observer.EVENT_REQ_RSP, observer.Listener{
|
||||
OnNotify: func(data interface{}, args ...interface{}) {
|
||||
if data == nil {
|
||||
return
|
||||
}
|
||||
msg := data.(*pb.UserMessage)
|
||||
if t.MainType == msg.MainType && t.SubType == msg.SubType {
|
||||
if t.Print != nil {
|
||||
resLog.SetText(t.Print(msg))
|
||||
} else {
|
||||
resLog.SetText(msg.Data.String())
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
obs.AddListener(observer.EVENT_RST, observer.Listener{
|
||||
OnNotify: func(data interface{}, args ...interface{}) {
|
||||
tm := data.(time.Time)
|
||||
cost := time.Since(tm)
|
||||
// logrus.WithFields(logrus.Fields{"Main": t.MainType, "Sub": t.SubType, "cost": cost}).Debug("耗时")
|
||||
timeLbl.Text = fmt.Sprintf("耗时:%v", cost)
|
||||
timeLbl.Refresh()
|
||||
},
|
||||
})
|
||||
|
||||
resLog.Wrapping = fyne.TextWrapBreak
|
||||
formReq := view.CreateView(t)
|
||||
// required! Refresh updates the widget
|
||||
formReq.Refresh()
|
||||
formCard := widget.NewCard("", "", formReq)
|
||||
|
||||
clearBtn := widget.NewButtonWithIcon(common.APP_TESTCASE_BTN_CLEARLOG, theme.DeleteIcon(), func() {
|
||||
resLog.SetText("")
|
||||
})
|
||||
|
||||
resPanel := container.NewBorder(container.NewHBox(clearBtn, layout.NewSpacer(), timeLbl), nil, nil, nil, resLog)
|
||||
|
||||
panel := container.NewVSplit(
|
||||
formCard,
|
||||
resPanel,
|
||||
)
|
||||
panel.Offset = 0.8
|
||||
content.Objects = append(content.Objects, panel)
|
||||
} else {
|
||||
logrus.WithFields(logrus.Fields{"mainType": t.MainType, "subType": t.SubType}).Warn("no view")
|
||||
}
|
||||
|
||||
content.Refresh()
|
||||
}
|
||||
split := container.NewHSplit(a.makeNav(setNav), caseContent)
|
||||
split.Offset = 0.2
|
||||
a.tabItem.Content = container.NewBorder(nil, a.progress, nil, nil, split)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *appTester) makeNav(setNav func(testCase *model.TestCase)) fyne.CanvasObject {
|
||||
tree := &widget.Tree{
|
||||
ChildUIDs: func(uid string) (c []widget.TreeNodeID) {
|
||||
return pb2.CaseIndex[uid]
|
||||
},
|
||||
IsBranch: func(uid string) bool {
|
||||
children, ok := pb2.CaseIndex[uid]
|
||||
return ok && len(children) > 0
|
||||
},
|
||||
CreateNode: func(branch bool) fyne.CanvasObject {
|
||||
return widget.NewLabel("(empty)")
|
||||
},
|
||||
UpdateNode: func(uid string, branch bool, obj fyne.CanvasObject) {
|
||||
t, ok := pb2.CaseNav[uid]
|
||||
if !ok {
|
||||
logrus.WithField("id", uid).Warnf("Missing tutorial panel")
|
||||
return
|
||||
}
|
||||
if a.disEnabled(t) {
|
||||
obj.(*widget.Label).TextStyle = fyne.TextStyle{Italic: true}
|
||||
if branch { //parent
|
||||
obj.(*widget.Label).SetText(fmt.Sprintf("%s(dis0)", t.MainType))
|
||||
} else {
|
||||
// obj.(*widget.Label).SetText(fmt.Sprintf("%s(dis1)", t.SubType))
|
||||
}
|
||||
} else {
|
||||
if branch { //parent
|
||||
obj.(*widget.Label).TextStyle = fyne.TextStyle{Bold: true}
|
||||
if t.NavLabel != "" {
|
||||
obj.(*widget.Label).SetText(t.NavLabel)
|
||||
} else {
|
||||
obj.(*widget.Label).SetText(t.MainType)
|
||||
}
|
||||
} else {
|
||||
if t.NavLabel != "" {
|
||||
obj.(*widget.Label).SetText(t.NavLabel)
|
||||
} else {
|
||||
obj.(*widget.Label).SetText(t.SubType)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
OnSelected: func(uid string) {
|
||||
if t, ok := pb2.CaseNav[uid]; ok {
|
||||
logrus.WithFields(logrus.Fields{"mainType": t.MainType, "subType": t.SubType}).Debug("select")
|
||||
if a.disEnabled(t) {
|
||||
return
|
||||
}
|
||||
if t.SubType == "" {
|
||||
return
|
||||
}
|
||||
a.progress.Start()
|
||||
a.progress.Show()
|
||||
go setNav(t)
|
||||
}
|
||||
},
|
||||
}
|
||||
return container.NewBorder(nil, nil, nil, nil, tree)
|
||||
}
|
||||
|
||||
func (a *appTester) ShortCut() fyne.Shortcut {
|
||||
return &desktop.CustomShortcut{KeyName: fyne.Key2, Modifier: desktop.AltModifier}
|
||||
}
|
||||
|
||||
func (a *appTester) Icon() fyne.Resource {
|
||||
return theme.DocumentIcon()
|
||||
}
|
||||
|
||||
func (a *appTester) Pressure() bool {
|
||||
return true
|
||||
}
|
10
cmd/v2/ui/basewindow.go
Normal file
10
cmd/v2/ui/basewindow.go
Normal file
@ -0,0 +1,10 @@
|
||||
package ui
|
||||
|
||||
import "go_dreamfactory/cmd/v2/lib/common"
|
||||
|
||||
type WindowDefaultOptions struct {
|
||||
windowAction common.WindowAction
|
||||
windowMode common.WindowMode
|
||||
windowAspect common.WindowAspect
|
||||
// windowVisible bool
|
||||
}
|
57
cmd/v2/ui/cz_box_layout.go
Normal file
57
cmd/v2/ui/cz_box_layout.go
Normal file
@ -0,0 +1,57 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
)
|
||||
|
||||
// Declare conformity with Layout interface
|
||||
var _ fyne.Layout = (*CZBoxLayout)(nil)
|
||||
|
||||
// CZBoxLayout is a grid layout that support custom size of object
|
||||
// Now only support vertical mode
|
||||
type CZBoxLayout struct {
|
||||
vertical bool
|
||||
}
|
||||
|
||||
func NewVCZBoxLayout() fyne.Layout {
|
||||
return &CZBoxLayout{vertical: true}
|
||||
}
|
||||
|
||||
func (c *CZBoxLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) {
|
||||
pos := fyne.NewPos(0, 0)
|
||||
for _, child := range objects {
|
||||
if !child.Visible() {
|
||||
continue
|
||||
}
|
||||
|
||||
child.Move(pos)
|
||||
size := child.Size()
|
||||
if c.vertical {
|
||||
pos = pos.Add(fyne.NewPos(0, size.Height+theme.Padding()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CZBoxLayout) MinSize(objects []fyne.CanvasObject) fyne.Size {
|
||||
minSize := fyne.NewSize(0, 0)
|
||||
addPadding := false
|
||||
for _, child := range objects {
|
||||
if !child.Visible() {
|
||||
continue
|
||||
}
|
||||
|
||||
if c.vertical {
|
||||
size := child.Size()
|
||||
minSize.Width = fyne.Max(size.Width, minSize.Width)
|
||||
minSize.Height += size.Height
|
||||
if addPadding {
|
||||
minSize.Height += theme.Padding()
|
||||
}
|
||||
}
|
||||
|
||||
addPadding = true
|
||||
}
|
||||
|
||||
return minSize
|
||||
}
|
49
cmd/v2/ui/log_viewer.go
Normal file
49
cmd/v2/ui/log_viewer.go
Normal file
@ -0,0 +1,49 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type logViewer struct {
|
||||
logArea *widget.Entry
|
||||
refresh *widget.Button
|
||||
|
||||
Win fyne.Window
|
||||
}
|
||||
|
||||
func newLogViewer() *logViewer {
|
||||
var lv logViewer
|
||||
|
||||
lv.logArea = widget.NewMultiLineEntry()
|
||||
lv.logArea.Disable()
|
||||
lv.logArea.Wrapping = fyne.TextWrapBreak
|
||||
|
||||
lv.initLogContent()
|
||||
|
||||
lv.refresh = widget.NewButtonWithIcon(string(theme.ColorNameFocus), theme.ViewRefreshIcon(), func() {
|
||||
// lv.initLogContent()
|
||||
})
|
||||
|
||||
lv.Win = fyne.CurrentApp().NewWindow("日志")
|
||||
lv.Win.SetContent(container.NewBorder(
|
||||
container.NewHBox(layout.NewSpacer(), lv.refresh), nil, nil, nil,
|
||||
lv.logArea))
|
||||
lv.Win.Resize(fyne.NewSize(800, 600))
|
||||
lv.Win.CenterOnScreen()
|
||||
|
||||
return &lv
|
||||
}
|
||||
|
||||
func (lv *logViewer) initLogContent() {
|
||||
cont := ""
|
||||
// globalLogWriter.Traversal(func(s string) {
|
||||
// cont += s
|
||||
// })
|
||||
|
||||
// lv.logArea.CursorRow = globalLogWriter.Size()
|
||||
lv.logArea.SetText(cont)
|
||||
}
|
70
cmd/v2/ui/main_menu.go
Normal file
70
cmd/v2/ui/main_menu.go
Normal file
@ -0,0 +1,70 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type mainMenu struct {
|
||||
*fyne.MainMenu
|
||||
sysMenu *fyne.Menu
|
||||
appMenus []*fyne.MenuItem
|
||||
|
||||
settingMenu *fyne.Menu
|
||||
testingMenu *fyne.MenuItem
|
||||
|
||||
quite *fyne.MenuItem
|
||||
|
||||
helpMenu *fyne.Menu
|
||||
sysLog *fyne.MenuItem
|
||||
// aboutSelf *fyne.MenuItem
|
||||
}
|
||||
|
||||
func newMainMenu() *mainMenu {
|
||||
var mm mainMenu
|
||||
|
||||
// system
|
||||
mm.appMenus = make([]*fyne.MenuItem, len(appRegister))
|
||||
for i, app := range appRegister {
|
||||
app := app
|
||||
mm.appMenus[i] = fyne.NewMenuItem(app.GetAppName(), func() {
|
||||
err := globalWin.at.openApp(app)
|
||||
if err != nil {
|
||||
logrus.Errorf("打开 %s, err:%v", app.GetAppName(), err)
|
||||
}
|
||||
})
|
||||
mm.appMenus[i].Icon = app.Icon()
|
||||
}
|
||||
|
||||
mm.quite = fyne.NewMenuItem("退出", globalWin.quiteHandle)
|
||||
mm.quite.Icon = theme.LogoutIcon()
|
||||
mm.quite.IsQuit = true
|
||||
mm.sysMenu = fyne.NewMenu("应用", mm.appMenus...)
|
||||
mm.sysMenu.Items = append(mm.sysMenu.Items, fyne.NewMenuItemSeparator(), mm.quite)
|
||||
|
||||
// setting
|
||||
mm.testingMenu = fyne.NewMenuItem("压测配置", func() {
|
||||
newTestConfigWindow().Win.Show()
|
||||
})
|
||||
mm.testingMenu.Icon = theme.SettingsIcon()
|
||||
mm.settingMenu = fyne.NewMenu("设置",
|
||||
mm.testingMenu,
|
||||
)
|
||||
|
||||
// help
|
||||
mm.sysLog = fyne.NewMenuItem("日志", func() {
|
||||
newLogViewer().Win.Show()
|
||||
})
|
||||
mm.helpMenu = fyne.NewMenu("帮助",
|
||||
mm.sysLog,
|
||||
// mm.aboutSelf,
|
||||
)
|
||||
|
||||
mm.MainMenu = fyne.NewMainMenu(
|
||||
mm.sysMenu,
|
||||
// mm.settingMenu,
|
||||
// mm.helpMenu,
|
||||
)
|
||||
return &mm
|
||||
}
|
457
cmd/v2/ui/mainwindow.go
Normal file
457
cmd/v2/ui/mainwindow.go
Normal file
@ -0,0 +1,457 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/cmd/v2/lib/storage"
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
"go_dreamfactory/comm"
|
||||
// "go_dreamfactory/modules/user"
|
||||
"go_dreamfactory/pb"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/BabySid/gobase"
|
||||
"github.com/Pallinder/go-randomdata"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
var (
|
||||
globalWin *MainWindowImpl
|
||||
)
|
||||
|
||||
type MainWindow interface {
|
||||
WindowInterface
|
||||
}
|
||||
|
||||
type MainWindowImpl struct {
|
||||
UIImpl
|
||||
WindowDefaultOptions
|
||||
parent fyne.Window
|
||||
w fyne.Window
|
||||
tb *toolBar //工具条
|
||||
toys *toys // side
|
||||
sb *statusBar //状态栏
|
||||
at *appContainer //tabs
|
||||
mm *mainMenu //菜单
|
||||
}
|
||||
|
||||
func NewMainWindow(ui *UIImpl, parent fyne.Window) MainWindow {
|
||||
gobase.NewScheduler().Start()
|
||||
gobase.RegisterAtExit(gobase.GlobalScheduler.Stop)
|
||||
mw := &MainWindowImpl{
|
||||
UIImpl: *ui,
|
||||
parent: parent,
|
||||
}
|
||||
|
||||
globalWin = mw
|
||||
|
||||
ui.obs.AddListener(observer.EVENT_PING, observer.Listener{
|
||||
OnNotify: func(data interface{}, args ...interface{}) {
|
||||
ui.obs.Remove(observer.EVENT_PING)
|
||||
logrus.Debug("即将与服务器断开链接")
|
||||
conf := dialog.NewConfirm("链接中断", data.(error).Error(), func(
|
||||
b bool) {
|
||||
ui.app.Quit()
|
||||
}, globalWin.w)
|
||||
conf.SetDismissText("取消")
|
||||
conf.SetConfirmText("退出")
|
||||
conf.Show()
|
||||
},
|
||||
})
|
||||
|
||||
return mw
|
||||
}
|
||||
|
||||
// createWindowContainer create a container with the window content
|
||||
func (ui *MainWindowImpl) createWindowContainer() {
|
||||
// create main layout
|
||||
|
||||
// status bar
|
||||
ui.sb = newStatusBar()
|
||||
|
||||
// tool bar
|
||||
toolbar := widget.NewToolbar(
|
||||
// widget.NewToolbarAction(theme.MediaVideoIcon(), func() {
|
||||
// openApp(ui.at, common.TOOLBAR_MONITOR)
|
||||
// }),
|
||||
// widget.NewToolbarAction(theme.DocumentIcon(), func() {
|
||||
// openApp(ui.at, common.TOOLBAR_TESTER)
|
||||
// }),
|
||||
// widget.NewToolbarAction(theme.StorageIcon(), func() {
|
||||
// openApp(ui.at, common.TOOLBAR_AUTO)
|
||||
// }),
|
||||
// widget.NewToolbarSpacer(),
|
||||
// widget.NewToolbarAction(theme.FileIcon(), func() {
|
||||
// newLogViewer().Win.Show()
|
||||
// }),
|
||||
)
|
||||
ui.tb = newToolBar(toolbar)
|
||||
|
||||
// Fun Toys
|
||||
ui.toys = newToys(ui.obs)
|
||||
|
||||
// Main Menu
|
||||
ui.mm = newMainMenu()
|
||||
ui.w.SetMainMenu(ui.mm.MainMenu)
|
||||
|
||||
// main app tabs
|
||||
ui.at = newAppContainer(appRegister, ui.pttService, ui.obs)
|
||||
content := container.NewBorder(ui.tb.toolbar, ui.sb.widget, nil, ui.toys.widget, ui.at)
|
||||
ui.w.SetContent(content)
|
||||
ui.w.CenterOnScreen()
|
||||
ui.w.SetCloseIntercept(ui.quiteHandle)
|
||||
}
|
||||
|
||||
func (ui *MainWindowImpl) SetStatusMsg(msg string) {
|
||||
ui.sb.setMessage(fmt.Sprintf("err:%s", msg))
|
||||
}
|
||||
|
||||
func (ui *MainWindowImpl) quiteHandle() {
|
||||
dialog.ShowConfirm("提示", "确定退出吗", func(b bool) {
|
||||
if !b {
|
||||
return
|
||||
}
|
||||
ui.app.Quit()
|
||||
}, ui.w)
|
||||
}
|
||||
|
||||
// CreateWindow ....
|
||||
func (ui *MainWindowImpl) CreateWindow(_ string, width, height float32, _ bool) {
|
||||
// init window
|
||||
title := fmt.Sprintf(common.APP_WIN_TITLE, "登录", ui.app.Metadata().Version, ui.app.Metadata().Build, common.APP_NAME)
|
||||
w := ui.app.NewWindow(title)
|
||||
ui.AddWindow("main", w)
|
||||
ui.w = w
|
||||
|
||||
if ui.windowAspect == common.WindowAspect_FullScreen {
|
||||
w.SetFullScreen(true)
|
||||
} else {
|
||||
w.Resize(fyne.NewSize(width, height))
|
||||
}
|
||||
|
||||
// w.SetMaster()
|
||||
w.CenterOnScreen()
|
||||
w.SetCloseIntercept(func() {
|
||||
ui.parent.Show()
|
||||
})
|
||||
_ = ui.createChooseServerPopUp(w)
|
||||
}
|
||||
|
||||
// createChooseServerPopUp
|
||||
func (ui *MainWindowImpl) createChooseServerPopUp(w fyne.Window) error {
|
||||
ch := make(chan string)
|
||||
|
||||
title := fmt.Sprintf(common.APP_WIN_TITLE, "选服", ui.app.Metadata().Version, ui.app.Metadata().Build, common.APP_NAME)
|
||||
selServerWin := ui.createChooseServerWindow(title, ch)
|
||||
|
||||
go func() {
|
||||
data := <-ch
|
||||
selServerWin.Hide()
|
||||
ui.NewWelcomeLabel(data)
|
||||
ui.w.Show()
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ui *MainWindowImpl) configForm(w fyne.Window, call func()) *widget.Form {
|
||||
//区服编号
|
||||
sId := widget.NewEntry()
|
||||
//区服地址
|
||||
sAddr := widget.NewEntry()
|
||||
//区服名称
|
||||
sName := widget.NewEntry()
|
||||
configForm := widget.NewForm()
|
||||
configForm.AppendItem(widget.NewFormItem("区服编号", sId))
|
||||
configForm.AppendItem(widget.NewFormItem("区服地址", sAddr))
|
||||
configForm.AppendItem(widget.NewFormItem("区服名称", sName))
|
||||
|
||||
configForm.OnSubmit = func() {
|
||||
defer func() {
|
||||
w.Close()
|
||||
call()
|
||||
}()
|
||||
ui.config.Servers = append(ui.config.Servers, &storage.ServerConfig{
|
||||
Name: sName.Text,
|
||||
SId: sId.Text,
|
||||
Url: sAddr.Text,
|
||||
})
|
||||
if err := ui.storage.StoreConfig(ui.config); err != nil {
|
||||
dialog.ShowError(err, w)
|
||||
return
|
||||
}
|
||||
}
|
||||
configForm.SubmitText = "保存配置"
|
||||
configForm.Refresh()
|
||||
return configForm
|
||||
}
|
||||
|
||||
// createChooseServerWindow
|
||||
func (ui *MainWindowImpl) createChooseServerWindow(title string, ch chan string) fyne.Window {
|
||||
w := fyne.CurrentApp().NewWindow(title)
|
||||
// choose server button func
|
||||
makeButton := func(s *storage.ServerConfig, parent fyne.Window) *widget.Button {
|
||||
btn := widget.NewButton(s.Name, func() {
|
||||
d := dialog.NewInformation("", common.INFO_WAIT, parent)
|
||||
d.SetDismissText(common.BUTTON_CANCEL)
|
||||
d.Show()
|
||||
|
||||
logrus.WithFields(logrus.Fields{"server": s.Name, "sid": s.SId}).Debug("choose server")
|
||||
//conn server
|
||||
if err := ui.connService.WsConnect(s.Url); err != nil {
|
||||
d.Hide()
|
||||
dialog.ShowError(err, parent)
|
||||
} else {
|
||||
ch <- fmt.Sprintf("%s:%s", s.SId, s.Name)
|
||||
}
|
||||
})
|
||||
return btn
|
||||
}
|
||||
|
||||
sGrid := container.NewGridWithColumns(2)
|
||||
|
||||
if len(ui.config.Servers) == 0 {
|
||||
c := storage.NewDefaultConfig()
|
||||
ui.config.Servers = append(ui.config.Servers, c.Servers...)
|
||||
}
|
||||
|
||||
if len(ui.config.Servers) != 0 {
|
||||
for _, s := range ui.config.Servers {
|
||||
box := makeButton(s, w)
|
||||
sGrid.Add(container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.DeleteIcon(), func() {
|
||||
defer func() {
|
||||
w.Close()
|
||||
ui.parent.Show()
|
||||
}()
|
||||
txt := box.Text
|
||||
for i, ss := range ui.config.Servers {
|
||||
if txt == ss.Name {
|
||||
ui.config.Servers = append(ui.config.Servers[:i], ui.config.Servers[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
if err := ui.storage.StoreConfig(ui.config); err != nil {
|
||||
dialog.ShowError(err, w)
|
||||
}
|
||||
|
||||
}), box))
|
||||
}
|
||||
sGrid.Add(widget.NewButtonWithIcon("", theme.ContentAddIcon(), func() {
|
||||
addWin := fyne.CurrentApp().NewWindow("添加区服")
|
||||
addWin.SetContent(ui.configForm(addWin, func() {
|
||||
w.Close()
|
||||
ui.parent.Show()
|
||||
}))
|
||||
addWin.SetFixedSize(true)
|
||||
addWin.Resize(fyne.NewSize(500, 200))
|
||||
addWin.Show()
|
||||
addWin.CenterOnScreen()
|
||||
}))
|
||||
w.SetContent(sGrid)
|
||||
} else {
|
||||
w.SetContent(ui.configForm(w, func() {
|
||||
w.Close()
|
||||
ui.parent.Show()
|
||||
}))
|
||||
}
|
||||
|
||||
w.SetFixedSize(true)
|
||||
w.Resize(fyne.NewSize(500, 200))
|
||||
w.Show()
|
||||
w.SetCloseIntercept(func() {
|
||||
ui.parent.Show()
|
||||
w.Close()
|
||||
})
|
||||
w.CenterOnScreen()
|
||||
return w
|
||||
}
|
||||
|
||||
// createLoginWin
|
||||
func (ui *MainWindowImpl) createLoginWin(sid, sname string) {
|
||||
account := widget.NewEntry()
|
||||
// account.Text = "user8080" //default account
|
||||
|
||||
items := []*widget.FormItem{
|
||||
widget.NewFormItem(common.LABEL_ACCOUNT, account),
|
||||
}
|
||||
|
||||
dialog.ShowForm(common.FORM_TITLE_LOGIN, common.BUTTON_LOGIN, common.BUTTON_CANCEL, items, func(b bool) {
|
||||
if !b {
|
||||
logrus.Debug("cancel login")
|
||||
} else {
|
||||
if account.Text != "" {
|
||||
logrus.WithField("account", account.Text).Debug("submit login")
|
||||
ui.createWindowContainer()
|
||||
appName, err := ui.at.openDefaultApp(common.TOOLBAR_MONITOR)
|
||||
if err != nil {
|
||||
logrus.WithField("appName", appName).Error(err)
|
||||
}
|
||||
// hide toolbar
|
||||
ui.tb.toolbar.Hide()
|
||||
// call after ui.createWindowContainer
|
||||
ui.connService.ListenerPush()
|
||||
if errdata := ui.pttService.Login(sid, account.Text); errdata != nil {
|
||||
err := fmt.Errorf("login err: %v[%d]", errdata, int32(errdata.Code))
|
||||
dialog.ShowError(err, ui.w)
|
||||
} else {
|
||||
ui.obs.AddListener(observer.EVENT_REQ_RSP, observer.Listener{
|
||||
OnNotify: func(data interface{}, args ...interface{}) {
|
||||
if data == nil {
|
||||
return
|
||||
}
|
||||
msg := data.(*pb.UserMessage)
|
||||
if msg.MainType == string("user") &&
|
||||
msg.SubType == "login" {
|
||||
rsp := &pb.UserLoginResp{}
|
||||
if !comm.ProtoUnmarshal(msg, rsp) {
|
||||
logrus.Error("unmarshal err")
|
||||
return
|
||||
}
|
||||
|
||||
//ping
|
||||
go func() {
|
||||
timer := time.NewTimer(10 * time.Second)
|
||||
for {
|
||||
if !timer.Stop() {
|
||||
select {
|
||||
case <-timer.C:
|
||||
default:
|
||||
}
|
||||
}
|
||||
timer.Reset(10 * time.Second)
|
||||
select {
|
||||
case <-timer.C:
|
||||
ui.pttService.Ping(sid, account.Text)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}()
|
||||
// reset main window title
|
||||
subTitle := fmt.Sprintf("%s[%s]", sname, sid)
|
||||
ui.w.SetTitle(fmt.Sprintf(common.APP_WIN_TITLE, subTitle, ui.app.Metadata().Version, ui.app.Metadata().Build, common.APP_NAME))
|
||||
ui.pttService.SetUser(rsp.Data, rsp.Ex)
|
||||
// isCreateRole
|
||||
if rsp.Data.Created {
|
||||
// set statusbar message
|
||||
ui.sb.setMessage(common.LABEL_WELCOME + rsp.Data.Binduid)
|
||||
// update userinfo
|
||||
ui.obs.Notify(observer.EVENT_USERINFO, ui.pttService.GetUser())
|
||||
// show toolbar
|
||||
ui.tb.toolbar.Show()
|
||||
} else {
|
||||
// create role
|
||||
ui.createRoleWindowPopUp()
|
||||
}
|
||||
} else if msg.MainType == "notify" && msg.SubType == "errornotify" {
|
||||
push := &pb.NotifyErrorNotifyPush{}
|
||||
if !comm.ProtoUnmarshal(msg, push) {
|
||||
logrus.Error("unmarsh err")
|
||||
return
|
||||
}
|
||||
|
||||
if push.Code == pb.ErrorCode_UserLogined {
|
||||
cf := dialog.NewError(errors.New("【"+account.Text+"】账号已在其它终端登录,退出重新登录"), ui.w)
|
||||
cf.SetOnClosed(func() {
|
||||
ui.app.Quit()
|
||||
})
|
||||
cf.Show()
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}, ui.w)
|
||||
}
|
||||
|
||||
// createMainWindowMenu create the main window menu
|
||||
func (ui *MainWindowImpl) createMainWindowMenu() *fyne.MainMenu {
|
||||
|
||||
menuItems := []*fyne.MenuItem{}
|
||||
|
||||
menu := fyne.Menu{
|
||||
Label: common.MENU_FILE,
|
||||
Items: menuItems,
|
||||
}
|
||||
|
||||
return fyne.NewMainMenu(&menu)
|
||||
}
|
||||
|
||||
// createRoleWindowPopUp
|
||||
func (ui *MainWindowImpl) createRoleWindowPopUp() {
|
||||
nickname := widget.NewEntry()
|
||||
c := container.NewBorder(nil, nil, nil,
|
||||
widget.NewButtonWithIcon("", theme.ViewRefreshIcon(), func() {
|
||||
nickname.SetText(randomdata.SillyName())
|
||||
}),
|
||||
nickname,
|
||||
)
|
||||
figure := widget.NewEntry()
|
||||
figure.PlaceHolder = "形象ID"
|
||||
figure.Text = "1"
|
||||
|
||||
var gender int32
|
||||
genderSel := widget.NewSelect([]string{"男", "女"}, func(s string) {
|
||||
if s == "男" {
|
||||
gender = 0
|
||||
} else if s == "女" {
|
||||
gender = 1
|
||||
}
|
||||
})
|
||||
genderSel.Selected = "男"
|
||||
|
||||
items := []*widget.FormItem{
|
||||
widget.NewFormItem("性别", genderSel),
|
||||
widget.NewFormItem("形象", figure),
|
||||
widget.NewFormItem(common.LABEL_NICKNAME, c),
|
||||
}
|
||||
|
||||
d := dialog.NewForm(common.FORM_TITLE_CREATEROLE, common.BUTTON_OK, common.BUTTON_CANCEL, items, func(b bool) {
|
||||
if nickname.Text != "" {
|
||||
logrus.WithField("nickname", nickname.Text).Debug("submit crete role")
|
||||
if errdata := ui.pttService.CreateRole(nickname.Text, gender, cast.ToInt32(figure.Text)); errdata != nil {
|
||||
err := fmt.Errorf("login err: %v[%d]", errdata, int32(errdata.Code))
|
||||
dialog.ShowError(err, ui.w)
|
||||
} else {
|
||||
user := ui.pttService.GetUser()
|
||||
logrus.WithField("uid", user.DbUser.Uid).Debug("create role succ")
|
||||
ui.obs.Notify(observer.EVENT_USERINFO, ui.pttService.GetUser())
|
||||
ui.tb.toolbar.Show()
|
||||
}
|
||||
}
|
||||
}, ui.w)
|
||||
d.Resize(fyne.NewSize(300, 200))
|
||||
d.Show()
|
||||
}
|
||||
|
||||
// NewWelcomeLabel
|
||||
func (ui *MainWindowImpl) NewWelcomeLabel(data string) {
|
||||
p := strings.Split(data, ":")
|
||||
if len(p) != 2 {
|
||||
logrus.WithField("param", p).Error("choose service")
|
||||
return
|
||||
}
|
||||
c := container.NewCenter(container.NewVBox(
|
||||
widget.NewLabelWithStyle(fmt.Sprintf(common.LABEL_CHOOSE, p[0], p[1]),
|
||||
fyne.TextAlignCenter,
|
||||
fyne.TextStyle{Bold: true}),
|
||||
container.NewCenter(container.NewHBox(
|
||||
widget.NewButton(common.BUTTON_LOGIN, func() {
|
||||
ui.createLoginWin(p[0], p[1])
|
||||
}),
|
||||
)),
|
||||
))
|
||||
ui.w.SetContent(c)
|
||||
ui.w.SetCloseIntercept(func() {
|
||||
ui.w.Close()
|
||||
ui.parent.Show()
|
||||
})
|
||||
}
|
127
cmd/v2/ui/navview.go
Normal file
127
cmd/v2/ui/navview.go
Normal file
@ -0,0 +1,127 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/cmd/v2/model"
|
||||
"go_dreamfactory/cmd/v2/service"
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
formview "go_dreamfactory/cmd/v2/ui/views"
|
||||
|
||||
// "go_dreamfactory/modules/friend"
|
||||
// "go_dreamfactory/modules/growtask"
|
||||
// "go_dreamfactory/modules/hero"
|
||||
// "go_dreamfactory/modules/library"
|
||||
// "go_dreamfactory/modules/linestory"
|
||||
// "go_dreamfactory/modules/mline"
|
||||
// "go_dreamfactory/modules/sociaty"
|
||||
// "go_dreamfactory/modules/task"
|
||||
// "go_dreamfactory/modules/user"
|
||||
// "go_dreamfactory/modules/worldtask"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type MyCaseView interface {
|
||||
Init(service service.PttService, obs observer.Observer, w fyne.Window, res *widget.Entry)
|
||||
CreateView(t *model.TestCase) fyne.CanvasObject
|
||||
Load()
|
||||
}
|
||||
|
||||
// 1 注册接口测试的表单试图
|
||||
var (
|
||||
ViewRegister = map[string]MyCaseView{
|
||||
// gm
|
||||
common.MF("gm", "cmd"): &formview.BingoView{},
|
||||
// common.MF(comm.ModuleGM, "gi"): &formview.GlobalConfView{},
|
||||
// reddot
|
||||
// common.MF(comm.ModuleReddot, "get"): &formview.ReddotView{},
|
||||
//sys
|
||||
// common.MF(comm.ModuleSys, "funclist"): &formview.SysFuncListView{},
|
||||
//user
|
||||
// common.MF(comm.ModuleUser, user.UserSubTypeModifyAvatar): &formview.UserModifyavatarView{},
|
||||
// common.MF(comm.ModuleUser, user.UserSubTypeModifyName): &formview.UserModifynameView{},
|
||||
// common.MF(comm.ModuleUser, user.UserSubTypeModifyFigure): &formview.UserModifyfigureView{},
|
||||
// common.MF(comm.ModuleUser, user.UserSubTYpeModifyBgp): &formview.UserModifybgpView{},
|
||||
// common.MF(comm.ModuleUser, user.UserSubTypeModifySign): &formview.UserSignView{},
|
||||
// common.MF(comm.ModuleUser, user.UserSubTypeBattlerecord): &formview.UserBattlerecordView{},
|
||||
// items
|
||||
// common.MF(comm.ModuleItems, "getlist"): &formview.ItemListView{},
|
||||
// common.MF(comm.ModuleItems, "sellitem"): &formview.ItemsSellView{},
|
||||
// common.MF(comm.ModuleItems, "useitem"): &formview.ItemsUseView{},
|
||||
//mail
|
||||
// common.MF(comm.ModuleMail, "getlist"): &formview.MailListView{},
|
||||
// common.MF(comm.ModuleMail, "readmail"): &formview.MailReadMailView{},
|
||||
// common.MF(comm.ModuleMail, "delmail"): &formview.MailDelView{},
|
||||
// common.MF(comm.ModuleMail, "getusermailattachment"): &formview.MailAttachmentView{},
|
||||
// common.MF(comm.ModuleMail, "getallmailattachment"): &formview.MailAttachmentAllView{},
|
||||
//task
|
||||
// common.MF(comm.ModuleTask, task.TaskSubTypeList): &formview.TaskListView{},
|
||||
// common.MF(comm.ModuleTask, task.TaskSubTypeActiveList): &formview.TaskActiveListView{},
|
||||
// common.MF(comm.ModuleTask, task.TaskSubTypeActiveReceive): &formview.TaskActiveReceiveView{},
|
||||
// common.MF(comm.ModuleTask, task.TaskSubTypeGetrecord): &formview.RtaskRecordView{},
|
||||
// hero
|
||||
// common.MF(comm.ModuleHero, hero.HeroSubTypeList): &formview.HeroListView{},
|
||||
// common.MF(comm.ModuleHero, hero.StrengthenUplv): &formview.HeroStrengthenUplvView{},
|
||||
// common.MF(comm.ModuleHero, hero.StrengthenUpStar): &formview.HeroStrengthenUpStarView{},
|
||||
// common.MF(comm.ModuleHero, hero.DrawCard): &formview.HeroZhaomuView{},
|
||||
// common.MF(comm.ModuleHero, "info"): &formview.HeroInfoView{},
|
||||
//equip
|
||||
// common.MF(comm.ModuleEquipment, "getlist"): &formview.EquipListView{},
|
||||
// common.MF(comm.ModuleEquipment, "equip"): &formview.EquipUpDownView{},
|
||||
// common.MF(comm.ModuleEquipment, "upgrade"): &formview.EquipUpgradeView{},
|
||||
//friend
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeApply): &formview.FriendApplyView{},
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeAgree): &formview.FriendAgreeView{},
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeBlacklist): &formview.FriendBlacklistView{},
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeAddBlack): &formview.FriendAddBlackView{},
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeDelBlack): &formview.FriendDelblackView{},
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeSearch): &formview.FriendSearchView{},
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeRandList): &formview.FriendRandListView{},
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeGetreward): &formview.FriendGetrewardView{},
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeAssistlist): &formview.FriendAssistListView{},
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeAssistHero): &formview.FriendAssistHeroView{},
|
||||
// common.MF(comm.ModuleFriend, friend.FriendSubTypeAssistHeroList): &formview.FriendAssistHeroListView{},
|
||||
|
||||
// shop
|
||||
// common.MF(comm.ModuleShop, "getlist"): &formview.ShopListView{},
|
||||
// common.MF(comm.ModuleShop, "buy"): &formview.ShopBuyView{},
|
||||
// mailine
|
||||
// common.MF(comm.ModuleMline, mline.MlineGetListResp): &formview.MainlineListView{},
|
||||
// common.MF(comm.ModuleMline, mline.MlineChallengeResp): &formview.MainlineChallengeView{},
|
||||
// common.MF(comm.ModuleMline, mline.MlineGetRewardResp): &formview.MainlineRewardView{},
|
||||
// pagoda
|
||||
// common.MF(comm.ModulePagoda, "getlist"): &formview.PagodaListView{},
|
||||
// rtask
|
||||
common.MF("worldtask", "test"): &formview.RtaskTestView{},
|
||||
// linestory
|
||||
// common.MF(comm.ModuleLinestory, linestory.LinestorySubTypeChapter): &formview.LinestoryMineView{},
|
||||
// common.MF(comm.ModuleLibrary, library.LibraryFetterstoryTaskResp): &formview.FetterstoryView{},
|
||||
// gourmet
|
||||
// common.MF(comm.ModuleGourmet, "getranduser"): &formview.GourmentGetRandView{},
|
||||
// sociaty
|
||||
// common.MF(comm.ModuleSociaty, sociaty.SociatySubTypeList): &formview.SociatyListView{},
|
||||
// common.MF(comm.ModuleSociaty, sociaty.SociatySubTypeCreate): &formview.SociatyCreateView{},
|
||||
// common.MF(comm.ModuleSociaty, sociaty.SociatySubTypeMine): &formview.SociatyMineView{},
|
||||
// common.MF(comm.ModuleSociaty, sociaty.SociatySubTypeTasklist): &formview.SociatyTasklistView{},
|
||||
// common.MF(comm.ModuleSociaty, sociaty.SociatySubTypeRank): &formview.SociatyRankView{},
|
||||
// common.MF(comm.ModuleSociaty, "boss"): &formview.SociatyBossView{},
|
||||
// troll
|
||||
// common.MF(comm.ModuleTroll, "getlist"): &formview.TrollGetlistView{},
|
||||
// growtask
|
||||
// common.MF(comm.ModuleGrowtask, growtask.GrowtaskSubTypeList): &formview.GrowtaskListView{},
|
||||
//worldtask
|
||||
// common.MF(comm.ModuleWorldtask, worldtask.WorldtaskSubtypeMine): &formview.WorldtaskMineView{},
|
||||
// common.MF(comm.ModuleWorldtask, "check"): &formview.CheckWorldtaskView{},
|
||||
// common.MF(comm.ModuleWorldtask, "test"): &formview.RtaskTestView{},
|
||||
// //smithy
|
||||
common.MF("smithy", "tasklist"): &formview.SmithyView{},
|
||||
//武馆派遣
|
||||
// common.MF(comm.ModuleDispatch, "dispatch"): &formview.DispatchView{},
|
||||
// common.MF(comm.ModulePractice, "practice"): &formview.PracticeView{},
|
||||
//声望
|
||||
// common.MF(comm.ModuleReputation, "reputation"): &formview.ReputationView{},
|
||||
//旧时光
|
||||
// common.MF(comm.ModuleOldtimes, "oldtimes"): &formview.OldtimesView{},
|
||||
}
|
||||
)
|
26
cmd/v2/ui/status_bar.go
Normal file
26
cmd/v2/ui/status_bar.go
Normal file
@ -0,0 +1,26 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type statusBar struct {
|
||||
msgLabel *widget.Label
|
||||
widget *fyne.Container
|
||||
}
|
||||
|
||||
func newStatusBar() *statusBar {
|
||||
var sb statusBar
|
||||
sb.msgLabel = widget.NewLabel("")
|
||||
sb.widget = container.New(layout.NewHBoxLayout(),
|
||||
sb.msgLabel,
|
||||
layout.NewSpacer())
|
||||
return &sb
|
||||
}
|
||||
|
||||
func (sb *statusBar) setMessage(msg string) {
|
||||
sb.msgLabel.SetText(msg)
|
||||
}
|
71
cmd/v2/ui/testconfig_win.go
Normal file
71
cmd/v2/ui/testconfig_win.go
Normal file
@ -0,0 +1,71 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type TestConfigWindow struct {
|
||||
computer *widget.Button
|
||||
|
||||
Win fyne.Window
|
||||
}
|
||||
|
||||
func newTestConfigWindow() *TestConfigWindow {
|
||||
var configWin TestConfigWindow
|
||||
conf := globalWin.UIImpl.config
|
||||
|
||||
// 压测form
|
||||
timeoutEntry := widget.NewEntry()
|
||||
timeoutEntry.PlaceHolder = "毫秒数"
|
||||
timeoutEntry.Text = cast.ToString(conf.Pressure.TimeoutMs)
|
||||
|
||||
lpsEntry := widget.NewEntry()
|
||||
lpsEntry.PlaceHolder = "并发数量"
|
||||
lpsEntry.Text = cast.ToString(conf.Pressure.Concurrency)
|
||||
|
||||
durationEntry := widget.NewEntry()
|
||||
durationEntry.PlaceHolder = "秒数"
|
||||
durationEntry.Text = cast.ToString(conf.Pressure.DurationS)
|
||||
|
||||
form := widget.NewForm(
|
||||
widget.NewFormItem("超时(ms)", timeoutEntry),
|
||||
widget.NewFormItem("并发量", lpsEntry),
|
||||
widget.NewFormItem("持续时间(s)", durationEntry),
|
||||
)
|
||||
form.OnSubmit = func() {
|
||||
pressure := conf.Pressure
|
||||
pressure.TimeoutMs = cast.ToInt32(timeoutEntry.Text)
|
||||
pressure.Concurrency = 10
|
||||
pressure.DurationS = 2
|
||||
conf.Pressure = pressure
|
||||
if err := globalWin.UIImpl.storage.StoreConfig(conf); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
form.SubmitText = "确定"
|
||||
|
||||
// 计算器
|
||||
concurrencyEntry := widget.NewEntry()
|
||||
computerForm := widget.NewForm(
|
||||
widget.NewFormItem("并发", concurrencyEntry),
|
||||
)
|
||||
computerForm.OnSubmit = func() {
|
||||
}
|
||||
computerForm.SubmitText = "确定"
|
||||
|
||||
// layout
|
||||
configWin.Win = fyne.CurrentApp().NewWindow("压测配置")
|
||||
//压测配置
|
||||
settingLayout := container.NewBorder(widget.NewLabel("压测配置"), nil, nil, nil, form)
|
||||
// computer
|
||||
computerLayout := container.NewBorder(widget.NewLabel("并发量计算"), nil, nil, nil, computerForm)
|
||||
configWin.Win.SetContent(container.NewGridWithRows(2, settingLayout, computerLayout))
|
||||
configWin.Win.Resize(fyne.NewSize(800, 600))
|
||||
configWin.Win.CenterOnScreen()
|
||||
|
||||
return &configWin
|
||||
}
|
51
cmd/v2/ui/tool_bar.go
Normal file
51
cmd/v2/ui/tool_bar.go
Normal file
@ -0,0 +1,51 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type toolBar struct {
|
||||
toolbar *widget.Toolbar
|
||||
}
|
||||
|
||||
func newToolBar(items *widget.Toolbar) *toolBar {
|
||||
var tb toolBar
|
||||
|
||||
// mainwindow toolbar
|
||||
tb.toolbar = items
|
||||
return &tb
|
||||
}
|
||||
|
||||
// open app2
|
||||
func openApp(ac *appContainer, name string) {
|
||||
for _, app := range appRegister {
|
||||
if app.GetAppName() == name {
|
||||
err := ac.openApp(app)
|
||||
if err != nil {
|
||||
logrus.Error(fmt.Errorf("%s %v", app.GetAppName(), err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func openApp2(ac *appContainer, name string) {
|
||||
for _, app := range toolRegister {
|
||||
if app.GetAppName() == name {
|
||||
err := ac.openApp(app)
|
||||
if err != nil {
|
||||
logrus.Error(fmt.Errorf("%s %v", app.GetAppName(), err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func closeApp3(ac *appContainer, name string) {
|
||||
for _, appItem := range ac.Items {
|
||||
if appItem.Text == name {
|
||||
ac.Remove(appItem)
|
||||
}
|
||||
}
|
||||
}
|
436
cmd/v2/ui/tool_luban.go
Normal file
436
cmd/v2/ui/tool_luban.go
Normal file
@ -0,0 +1,436 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"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"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
fyne_storage "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 *common.ItemList
|
||||
jsonList *common.ItemList
|
||||
}
|
||||
|
||||
func (this *appGen) LazyInit(ptService service.PttService, obs observer.Observer) error {
|
||||
this.obs = obs
|
||||
this.goList = common.NewItemList()
|
||||
this.jsonList = common.NewItemList()
|
||||
|
||||
this.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_GEN, theme.ContentCopyIcon(), nil)
|
||||
|
||||
storage, _ := os_storage.NewOSStorage()
|
||||
conf, err := storage.LoadConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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 conf.LubanConf != nil {
|
||||
serverAddr.Text = conf.LubanConf.ServerAddr
|
||||
projectDir.Text = conf.LubanConf.ProjectDir
|
||||
workDir.Text = conf.LubanConf.WorkDir
|
||||
client.Text = conf.LubanConf.Client
|
||||
genType.Selected = conf.LubanConf.GenType
|
||||
genTypeText = conf.LubanConf.GenType
|
||||
tmpDir.Text = conf.LubanConf.TmpDir
|
||||
}
|
||||
|
||||
form := widget.NewForm(
|
||||
widget.NewFormItem("服务地址", serverAddr),
|
||||
widget.NewFormItem("项目目录", container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
|
||||
openFolder(projectDir, toolWin.w)
|
||||
}), projectDir)),
|
||||
widget.NewFormItem("工作目录", container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
|
||||
openFolder(workDir, toolWin.w)
|
||||
}), 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, toolWin.w)
|
||||
}), 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() {
|
||||
lubanconf := &os_storage.LubanConfig{
|
||||
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,
|
||||
}
|
||||
conf.LubanConf = lubanconf
|
||||
if err := storage.StoreConfig(conf); 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.CreateDefaultCheckList()
|
||||
|
||||
// 覆盖 -go
|
||||
go_allSelBtn := &widget.Button{Icon: theme.CheckButtonCheckedIcon()}
|
||||
go_allCancelBtn := &widget.Button{Icon: theme.CheckButtonIcon()}
|
||||
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.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.ChangeFileCount()
|
||||
// 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.CreateDefaultCheckList()
|
||||
|
||||
// 覆盖 -json
|
||||
json_allSelBtn := &widget.Button{Icon: theme.CheckButtonCheckedIcon()}
|
||||
json_allCancelBtn := &widget.Button{Icon: theme.CheckButtonIcon()}
|
||||
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("path", v).Debug("select 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_allSelBtn.OnTapped = func() {
|
||||
defer func() {
|
||||
json_allCancelBtn.Show()
|
||||
json_allSelBtn.Hide()
|
||||
}()
|
||||
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.ItemList.Refresh()
|
||||
}
|
||||
|
||||
//选择所有
|
||||
json_allCancelBtn.OnTapped = func() {
|
||||
defer func() {
|
||||
json_allCancelBtn.Hide()
|
||||
json_allSelBtn.Show()
|
||||
}()
|
||||
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()
|
||||
}
|
||||
|
||||
// 资源管理器
|
||||
explorBtn := &widget.Button{Text: "资源管理器", Icon: theme.FolderIcon()}
|
||||
explorBtn.OnTapped = func() {
|
||||
OpenExplor(filepath.Join(workDir.Text, inputDir.Text))
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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.ItemTotal))
|
||||
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.ItemTotal))
|
||||
json_overrideBtn.Show()
|
||||
this.jsonList.TitleLabel.Show()
|
||||
}
|
||||
|
||||
gen := func() {
|
||||
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
|
||||
}
|
||||
|
||||
// 更新列表
|
||||
if genTypeText == "go" {
|
||||
changeGo()
|
||||
} else if genTypeText == "json" {
|
||||
changeJson()
|
||||
} else if genTypeText == "all" {
|
||||
changeGo()
|
||||
changeJson()
|
||||
}
|
||||
}
|
||||
|
||||
dc := dialog.NewConfirm("提示", "Excel文件需要更新吗?", func(b bool) {
|
||||
if !b {
|
||||
gen()
|
||||
return
|
||||
}
|
||||
|
||||
OpenExplor(filepath.Join(workDir.Text, inputDir.Text))
|
||||
}, toolWin.w)
|
||||
dc.SetDismissText("不更新")
|
||||
dc.SetConfirmText("更新")
|
||||
dc.Show()
|
||||
}
|
||||
|
||||
//使用说明
|
||||
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, &layout.Spacer{}, explorBtn, 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
|
||||
}
|
||||
|
||||
// 打开目录
|
||||
func openFolder(entry *widget.Entry, w fyne.Window) {
|
||||
dConf := dialog.NewFolderOpen(func(lu fyne.ListableURI, err error) {
|
||||
if lu == nil {
|
||||
return
|
||||
}
|
||||
entry.Text = lu.Path()
|
||||
entry.Refresh()
|
||||
}, w)
|
||||
luri, _ := fyne_storage.ListerForURI(fyne_storage.NewFileURI("."))
|
||||
dConf.SetLocation(luri)
|
||||
dConf.SetConfirmText("打开")
|
||||
dConf.SetDismissText("取消")
|
||||
dConf.Resize(fyne.NewSize(750, 500))
|
||||
dConf.Show()
|
||||
}
|
||||
|
||||
func openFile(entry *widget.Entry, w fyne.Window) {
|
||||
dConf := dialog.NewFileOpen(func(lu fyne.URIReadCloser, err error) {
|
||||
if lu == nil {
|
||||
return
|
||||
}
|
||||
entry.SetText(lu.URI().Path())
|
||||
entry.Refresh()
|
||||
}, w)
|
||||
dConf.SetConfirmText("打开")
|
||||
dConf.SetDismissText("取消")
|
||||
dConf.SetFilter(fyne_storage.NewExtensionFileFilter([]string{".exe"}))
|
||||
dConf.Resize(fyne.NewSize(750, 500))
|
||||
dConf.Show()
|
||||
}
|
||||
|
||||
func (a *appGen) GetAppName() string {
|
||||
return common.TOOLBAR_GEN
|
||||
}
|
||||
func(a *appGen) Icon() fyne.Resource{
|
||||
return theme.ContentCopyIcon()
|
||||
}
|
53
cmd/v2/ui/tool_menu.go
Normal file
53
cmd/v2/ui/tool_menu.go
Normal file
@ -0,0 +1,53 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type toolMenu struct {
|
||||
*fyne.MainMenu
|
||||
sysMenu *fyne.Menu
|
||||
appMenus []*fyne.MenuItem
|
||||
|
||||
//退出
|
||||
quite *fyne.MenuItem
|
||||
|
||||
// 工具
|
||||
toolMenu *fyne.Menu
|
||||
//同步配置
|
||||
syncConfMenu *fyne.MenuItem
|
||||
}
|
||||
|
||||
func newToolMenu() *toolMenu {
|
||||
var mm toolMenu
|
||||
// system
|
||||
mm.appMenus = make([]*fyne.MenuItem, len(toolRegister))
|
||||
for i, app := range toolRegister {
|
||||
mm.appMenus[i] = fyne.NewMenuItem(app.GetAppName(), func() {
|
||||
err := toolWin.at.openApp(app)
|
||||
if err != nil {
|
||||
logrus.Errorf("打开 %s, err:%v", app.GetAppName(), err)
|
||||
}
|
||||
})
|
||||
mm.appMenus[i].Icon = app.Icon()
|
||||
}
|
||||
mm.quite = fyne.NewMenuItem("退出", toolWin.quiteHandle)
|
||||
mm.quite.Icon = theme.LogoutIcon()
|
||||
mm.quite.IsQuit = true
|
||||
mm.sysMenu = fyne.NewMenu("应用", mm.appMenus...)
|
||||
mm.sysMenu.Items = append(mm.sysMenu.Items, fyne.NewMenuItemSeparator(), mm.quite)
|
||||
|
||||
//tool
|
||||
mm.syncConfMenu = fyne.NewMenuItem("同步云配置", toolWin.syncConfig)
|
||||
mm.toolMenu = fyne.NewMenu("工具",
|
||||
mm.syncConfMenu,
|
||||
)
|
||||
|
||||
mm.MainMenu = fyne.NewMainMenu(
|
||||
mm.sysMenu,
|
||||
mm.toolMenu,
|
||||
)
|
||||
return &mm
|
||||
}
|
251
cmd/v2/ui/tool_mgo.go
Normal file
251
cmd/v2/ui/tool_mgo.go
Normal file
@ -0,0 +1,251 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"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"
|
||||
"go_dreamfactory/pb"
|
||||
"strings"
|
||||
|
||||
mytheme "go_dreamfactory/cmd/v2/theme"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"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"
|
||||
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type appMgo struct {
|
||||
appAdapter
|
||||
conf *os_storage.Config
|
||||
storage os_storage.Storage
|
||||
db *mongo.Database
|
||||
client *mongo.Client
|
||||
scriptEntry *widget.Entry
|
||||
}
|
||||
|
||||
func (this *appMgo) LazyInit(ptService service.PttService, obs observer.Observer) error {
|
||||
this.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_MGODB, theme.DownloadIcon(), nil)
|
||||
content := container.NewMax()
|
||||
content.Objects = []fyne.CanvasObject{}
|
||||
|
||||
this.scriptEntry = widget.NewMultiLineEntry()
|
||||
|
||||
connWinBtn := widget.NewButton("连接设置", this.showConWin)
|
||||
openConnBtn := widget.NewButton("打开连接", this.openConn)
|
||||
closeConnBtn := widget.NewButton("关闭连接", this.closeConn)
|
||||
createServerConfBtn := widget.NewButton("创建服务配置", this.createServerConf)
|
||||
btns := container.NewHBox(connWinBtn, openConnBtn, createServerConfBtn, layout.NewSpacer(), closeConnBtn)
|
||||
content.Objects = append(content.Objects, container.NewBorder(btns, nil, nil, nil, this.scriptEntry))
|
||||
this.tabItem.Content = content
|
||||
this.storage, _ = os_storage.NewOSStorage()
|
||||
var err error
|
||||
this.conf, err = this.storage.LoadConfig()
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *appMgo) openConn() {
|
||||
if this.conf.MgoDB == nil {
|
||||
dialog.ShowError(errors.New("MgoDB没有配置"), toolWin.w)
|
||||
return
|
||||
}
|
||||
var option *options.ClientOptions
|
||||
if (this.conf.MgoDB.User == "" && this.conf.MgoDB.Password == "") &&
|
||||
this.conf.MgoDB.Host != "" && this.conf.MgoDB.Port != 0 && this.conf.MgoDB.Database != "" {
|
||||
option = options.Client().ApplyURI(fmt.Sprintf("mongodb://%s:%d", this.conf.MgoDB.Host, this.conf.MgoDB.Port))
|
||||
} else {
|
||||
option = options.Client().ApplyURI(fmt.Sprintf("mongodb://%s:%s@%s:%d", this.conf.MgoDB.User, this.conf.MgoDB.Password,
|
||||
this.conf.MgoDB.Host, this.conf.MgoDB.Port))
|
||||
}
|
||||
client, err := mongo.Connect(context.TODO(), option)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
if err2 := client.Ping(context.TODO(), nil); err2 != nil {
|
||||
logrus.Error("Mongo连接失败", err2)
|
||||
return
|
||||
}
|
||||
this.db = client.Database(this.conf.MgoDB.Database)
|
||||
|
||||
this.scriptEntry.Text = this.db.Name() + " 连接成功"
|
||||
this.scriptEntry.Refresh()
|
||||
}
|
||||
|
||||
func (this *appMgo) closeConn() {
|
||||
if this.db != nil {
|
||||
if err := this.db.Client().Disconnect(context.TODO()); err != nil {
|
||||
this.scriptEntry.Text = "连接关闭失败"
|
||||
} else {
|
||||
this.scriptEntry.Text = "连接关闭成功"
|
||||
}
|
||||
this.scriptEntry.Refresh()
|
||||
}
|
||||
}
|
||||
|
||||
func (this *appMgo) createServerConf() {
|
||||
serverId := widget.NewEntry()
|
||||
serverName := widget.NewEntry()
|
||||
owner := widget.NewEntry()
|
||||
cross := widget.NewEntry()
|
||||
crossId := widget.NewEntry()
|
||||
singleserver := widget.NewEntry()
|
||||
opentime := widget.NewEntry()
|
||||
redisIsCluster := widget.NewEntry()
|
||||
redisAddr := widget.NewEntry()
|
||||
redisPassword := widget.NewEntry()
|
||||
redisDb := widget.NewEntry()
|
||||
mongoUrl := widget.NewEntry()
|
||||
mongoDatabase := widget.NewEntry()
|
||||
|
||||
form := widget.NewForm(
|
||||
widget.NewFormItem("serverid", serverId),
|
||||
widget.NewFormItem("serverName", serverName),
|
||||
widget.NewFormItem("owner", owner),
|
||||
widget.NewFormItem("cross", cross),
|
||||
widget.NewFormItem("crossId", crossId),
|
||||
widget.NewFormItem("singleserver", singleserver),
|
||||
widget.NewFormItem("opentime", opentime),
|
||||
widget.NewFormItem("redisIsCluster", redisIsCluster),
|
||||
widget.NewFormItem("redisAddr", redisAddr),
|
||||
widget.NewFormItem("redisPassword", redisPassword),
|
||||
widget.NewFormItem("redisDb", redisDb),
|
||||
widget.NewFormItem("mongoUrl", mongoUrl),
|
||||
widget.NewFormItem("mongoDatabase", mongoDatabase),
|
||||
)
|
||||
|
||||
if this.conf.ServiceDBInfo != nil {
|
||||
serverId.Text = this.conf.ServiceDBInfo.Serverid
|
||||
serverName.Text = this.conf.ServiceDBInfo.ServerName
|
||||
owner.Text = this.conf.ServiceDBInfo.Owner
|
||||
cross.Text = this.conf.ServiceDBInfo.Cross
|
||||
crossId.Text = this.conf.ServiceDBInfo.CrossId
|
||||
singleserver.Text = this.conf.ServiceDBInfo.Singleserver
|
||||
opentime.Text = cast.ToString(this.conf.ServiceDBInfo.Opentime)
|
||||
redisIsCluster.Text = cast.ToString(this.conf.ServiceDBInfo.RedisIsCluster)
|
||||
redisAddr.Text = strings.Join(this.conf.ServiceDBInfo.RedisAddr, ",")
|
||||
redisPassword.Text = this.conf.ServiceDBInfo.RedisPassword
|
||||
redisDb.Text = cast.ToString(this.conf.ServiceDBInfo.RedisDb)
|
||||
mongoUrl.Text = this.conf.ServiceDBInfo.MongodbUrl
|
||||
mongoDatabase.Text = this.conf.ServiceDBInfo.MongodbDatabase
|
||||
}
|
||||
|
||||
subBtn := widget.NewButton("保存", func() {
|
||||
this.conf.ServiceDBInfo = &pb.ServiceDBInfo{
|
||||
Serverid: serverId.Text,
|
||||
ServerName: serverName.Text,
|
||||
Owner: owner.Text,
|
||||
Cross: cross.Text,
|
||||
CrossId: crossId.Text,
|
||||
Singleserver: singleserver.Text,
|
||||
Opentime: cast.ToInt64(opentime.Text),
|
||||
RedisIsCluster: cast.ToBool(redisIsCluster.Text),
|
||||
RedisAddr: strings.Split(redisAddr.Text, ","),
|
||||
RedisPassword: redisPassword.Text,
|
||||
RedisDb: cast.ToInt32(redisDb.Text),
|
||||
MongodbUrl: mongoUrl.Text,
|
||||
MongodbDatabase: mongoDatabase.Text,
|
||||
}
|
||||
if err := this.storage.StoreConfig(this.conf); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
})
|
||||
subBtn.Importance = widget.HighImportance
|
||||
|
||||
execBtn := widget.NewButton("插入", func() {
|
||||
if this.db == nil {
|
||||
common.ShowTip("请先打开连接")
|
||||
return
|
||||
}
|
||||
c := this.db.Collection("serverdata")
|
||||
if _, err := c.InsertOne(context.TODO(), this.conf.ServiceDBInfo); err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.scriptEntry.Text = "插入成功"
|
||||
this.scriptEntry.Refresh()
|
||||
})
|
||||
dconf := dialog.NewCustom("配置", "关闭", container.NewVBox(form, container.NewHBox(layout.NewSpacer(), subBtn, execBtn)), toolWin.w)
|
||||
dconf.Resize(fyne.NewSize(400, 600))
|
||||
dconf.Show()
|
||||
|
||||
}
|
||||
|
||||
func (this *appMgo) showConWin() {
|
||||
|
||||
connName := widget.NewEntry()
|
||||
|
||||
address := widget.NewEntry()
|
||||
|
||||
port := widget.NewEntry()
|
||||
|
||||
user := widget.NewEntry()
|
||||
password := widget.NewPasswordEntry()
|
||||
|
||||
database := widget.NewEntry()
|
||||
|
||||
form := widget.NewForm(
|
||||
widget.NewFormItem("Name", connName),
|
||||
widget.NewFormItem("Address", container.NewBorder(nil, nil, nil, port, address)),
|
||||
widget.NewFormItem("User", user),
|
||||
widget.NewFormItem("Password", password),
|
||||
widget.NewFormItem("Database", database),
|
||||
)
|
||||
|
||||
if this.conf.MgoDB != nil {
|
||||
connName.Text = this.conf.MgoDB.Name
|
||||
address.Text = this.conf.MgoDB.Host
|
||||
port.Text = cast.ToString(this.conf.MgoDB.Port)
|
||||
user.Text = this.conf.MgoDB.User
|
||||
password.Text = this.conf.MgoDB.Password
|
||||
database.Text = this.conf.MgoDB.Database
|
||||
}
|
||||
form.OnSubmit = func() {
|
||||
this.conf.MgoDB = &os_storage.MgoDB{
|
||||
Name: connName.Text,
|
||||
Host: address.Text,
|
||||
Port: cast.ToInt32(port.Text),
|
||||
User: user.Text,
|
||||
Password: password.Text,
|
||||
Database: database.Text,
|
||||
}
|
||||
|
||||
if connName.Text == "" || address.Text == "" || port.Text == "" {
|
||||
common.ShowTip("请填写完整")
|
||||
return
|
||||
}
|
||||
if err := this.storage.StoreConfig(this.conf); err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
dialog.ShowInformation("提示", "保存成功", toolWin.w)
|
||||
}
|
||||
form.SubmitText = "保存"
|
||||
|
||||
dconf := dialog.NewCustom("设置链接", "关闭", form, toolWin.w)
|
||||
dconf.Resize(fyne.NewSize(400, 200))
|
||||
dconf.Show()
|
||||
}
|
||||
|
||||
func (a *appMgo) GetAppName() string {
|
||||
return common.TOOLBAR_MGODB
|
||||
}
|
||||
func (a *appMgo) Icon() fyne.Resource {
|
||||
return mytheme.ResourceMongodbJpg
|
||||
}
|
73
cmd/v2/ui/tool_newlock.go
Normal file
73
cmd/v2/ui/tool_newlock.go
Normal file
@ -0,0 +1,73 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/cmd/v2/service"
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
"image/color"
|
||||
"strconv"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/sethvargo/go-password/password"
|
||||
)
|
||||
|
||||
type appLock struct {
|
||||
appAdapter
|
||||
}
|
||||
|
||||
func (this *appLock) LazyInit(ptService service.PttService, obs observer.Observer) error {
|
||||
|
||||
this.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_SEC, theme.DownloadIcon(), nil)
|
||||
|
||||
content := container.NewMax()
|
||||
content.Objects = []fyne.CanvasObject{}
|
||||
|
||||
title := canvas.NewText("输入密码长度", color.White)
|
||||
|
||||
input := widget.NewEntry()
|
||||
input.SetPlaceHolder("长度范围10-63")
|
||||
|
||||
text := canvas.NewText("", color.White)
|
||||
text.TextSize = 16
|
||||
|
||||
btn := widget.NewButtonWithIcon("生成", theme.ConfirmIcon(), func() {
|
||||
passwordLength, _ := strconv.Atoi(input.Text)
|
||||
|
||||
//Avoids length errors
|
||||
if passwordLength <= 10 || passwordLength >= 63 {
|
||||
passwordLength = 10
|
||||
}
|
||||
|
||||
text.Text = password.MustGenerate(passwordLength, 5, 5, false, false)
|
||||
|
||||
text.Refresh()
|
||||
})
|
||||
|
||||
copybtn := widget.NewButtonWithIcon("复制密码", theme.ContentCopyIcon(), func() {
|
||||
if text.Text == "" {
|
||||
dialog.ShowError(errors.New("请生成密码"), toolWin.w)
|
||||
return
|
||||
}
|
||||
toolWin.w.Clipboard().SetContent(text.Text)
|
||||
common.ShowTip("已复制到剪贴板")
|
||||
})
|
||||
|
||||
c := container.NewVBox(title, input, text, btn, copybtn)
|
||||
content.Objects = append(content.Objects, c)
|
||||
|
||||
this.tabItem.Content = content
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *appLock) GetAppName() string {
|
||||
return common.TOOLBAR_SEC
|
||||
}
|
||||
func (a *appLock) Icon() fyne.Resource {
|
||||
return theme.DownloadIcon()
|
||||
}
|
263
cmd/v2/ui/tool_pb.go
Normal file
263
cmd/v2/ui/tool_pb.go
Normal file
@ -0,0 +1,263 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"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"
|
||||
"go_dreamfactory/utils"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
fyne_storage "fyne.io/fyne/v2/storage"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type appPbGen struct {
|
||||
appAdapter
|
||||
folderList *folderList
|
||||
}
|
||||
|
||||
func (this *appPbGen) LazyInit(ptService service.PttService, obs observer.Observer) error {
|
||||
this.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_PB, theme.ContentAddIcon(), nil)
|
||||
this.folderList = NewFolderList()
|
||||
|
||||
countLabel := widget.NewLabel("")
|
||||
|
||||
//load
|
||||
storage, _ := os_storage.NewOSStorage()
|
||||
conf, err := storage.LoadConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 打开目录
|
||||
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, _ := fyne_storage.ListerForURI(fyne_storage.NewFileURI("."))
|
||||
dConf.SetLocation(luri)
|
||||
dConf.SetConfirmText("打开")
|
||||
dConf.SetDismissText("取消")
|
||||
dConf.Resize(fyne.NewSize(750, 500))
|
||||
dConf.Show()
|
||||
}
|
||||
|
||||
content := container.NewMax()
|
||||
content.Objects = []fyne.CanvasObject{}
|
||||
|
||||
protoDir := widget.NewEntry()
|
||||
protoDir.PlaceHolder = "proto目录"
|
||||
protoDir.OnChanged = func(s string) {
|
||||
this.folderList.initItem(protoDir.Text)
|
||||
countLabel.SetText(fmt.Sprintf("总数:%v", this.folderList.fileTotal))
|
||||
}
|
||||
|
||||
outDir := widget.NewEntry()
|
||||
outDir.PlaceHolder = "go输出目录"
|
||||
|
||||
form := widget.NewForm(
|
||||
widget.NewFormItem("proto目录", container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
|
||||
openFolder(protoDir)
|
||||
this.folderList.initItem(protoDir.Text)
|
||||
}), protoDir)),
|
||||
widget.NewFormItem("输出目录", container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
|
||||
openFolder(outDir)
|
||||
}), outDir)),
|
||||
)
|
||||
|
||||
if conf.PbConf != nil {
|
||||
protoDir.SetText(conf.PbConf.ProtoDir)
|
||||
outDir.SetText(conf.PbConf.OutputDir)
|
||||
}
|
||||
|
||||
//打开资源管理器
|
||||
explorBtn := &widget.Button{Text: "资源管理器", Icon: theme.FolderIcon()}
|
||||
explorBtn.OnTapped = func() {
|
||||
OpenExplor(protoDir.Text)
|
||||
}
|
||||
|
||||
genBtn := &widget.Button{Text: "生成", Icon: theme.ConfirmIcon()}
|
||||
|
||||
genBtn.OnTapped = func() {
|
||||
genBtn.Disable()
|
||||
defer func() {
|
||||
genBtn.Enable()
|
||||
}()
|
||||
if runtime.GOOS != "windows" {
|
||||
dialog.ShowError(errors.New("no support "+runtime.GOOS), toolWin.w)
|
||||
return
|
||||
}
|
||||
dialog.ShowConfirm("确认",
|
||||
strings.Join(this.folderList.selItemIds, ","), func(b bool) {
|
||||
if !b {
|
||||
return
|
||||
}
|
||||
|
||||
if outDir.Text == "" {
|
||||
dialog.ShowError(errors.New("请设置输出目录"), toolWin.w)
|
||||
return
|
||||
}
|
||||
|
||||
if protoDir.Text == "" {
|
||||
dialog.ShowError(errors.New("请设置proto目录"), toolWin.w)
|
||||
return
|
||||
}
|
||||
|
||||
commandStr1 := `protoc --proto_path=%s --go_out=%s --go_opt=paths=import %s\*.proto`
|
||||
commandStr2 := `protoc --proto_path=%s --go_out=%s --go_opt=paths=import %s\%s\*.proto`
|
||||
var arg1, arg2 string
|
||||
arg1 = fmt.Sprintf(commandStr1,
|
||||
protoDir.Text,
|
||||
outDir.Text,
|
||||
protoDir.Text,
|
||||
)
|
||||
for _, name := range this.folderList.selItemIds {
|
||||
arg2 = fmt.Sprintf(commandStr2,
|
||||
protoDir.Text,
|
||||
outDir.Text,
|
||||
protoDir.Text,
|
||||
name,
|
||||
)
|
||||
}
|
||||
logrus.Debug(arg1)
|
||||
logrus.Debug(arg2)
|
||||
c1 := exec.Command("cmd.exe", "/c", arg1)
|
||||
if err := c1.Run(); err != nil {
|
||||
dialog.ShowError(err, toolWin.w)
|
||||
return
|
||||
}
|
||||
c2 := exec.Command("cmd.exe", "/c", arg2)
|
||||
if err := c2.Run(); err != nil {
|
||||
dialog.ShowError(err, toolWin.w)
|
||||
return
|
||||
}
|
||||
|
||||
}, toolWin.w)
|
||||
}
|
||||
|
||||
refreshBtn := widget.NewButtonWithIcon("", theme.ViewRefreshIcon(), func() {
|
||||
this.folderList.cachedList = common.NewList("")
|
||||
this.folderList.selItemIds = []string{}
|
||||
this.folderList.initItem(protoDir.Text)
|
||||
countLabel.SetText(fmt.Sprintf("总数:%v", this.folderList.fileTotal))
|
||||
})
|
||||
|
||||
confBtn := &widget.Button{Text: "保存配置", Icon: theme.DocumentSaveIcon()}
|
||||
confBtn.OnTapped = func() {
|
||||
pbconf := &os_storage.ProtobufConfig{
|
||||
ProtoDir: protoDir.Text,
|
||||
OutputDir: outDir.Text,
|
||||
}
|
||||
conf.PbConf = pbconf
|
||||
if err := storage.StoreConfig(conf); err != nil {
|
||||
logrus.WithField("err", err).Debug("保存配置")
|
||||
return
|
||||
}
|
||||
logrus.Debug("save pb conf")
|
||||
}
|
||||
|
||||
this.folderList.itemList = this.folderList.createList()
|
||||
|
||||
// layout
|
||||
c := container.NewBorder(
|
||||
form,
|
||||
container.NewHBox(confBtn, explorBtn, genBtn, refreshBtn, layout.NewSpacer(), countLabel), nil, nil,
|
||||
container.NewMax(
|
||||
container.NewVScroll(this.folderList.itemList),
|
||||
),
|
||||
)
|
||||
|
||||
content.Objects = append(content.Objects, c)
|
||||
this.tabItem.Content = content
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *appPbGen) GetAppName() string {
|
||||
return common.TOOLBAR_PB
|
||||
}
|
||||
func (a *appPbGen) Icon() fyne.Resource {
|
||||
return theme.ContentAddIcon()
|
||||
}
|
||||
|
||||
type folderList struct {
|
||||
selItemIds []string //选择的ID
|
||||
cachedList common.List
|
||||
itemList *widget.List
|
||||
fileTotal int //文件总数
|
||||
}
|
||||
|
||||
func NewFolderList() *folderList {
|
||||
return &folderList{
|
||||
cachedList: common.NewList(""),
|
||||
}
|
||||
}
|
||||
|
||||
func (f *folderList) createList() *widget.List {
|
||||
return widget.NewList(
|
||||
func() int {
|
||||
return len(f.cachedList.Items)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return widget.NewCheck("Template", func(b bool) {})
|
||||
},
|
||||
func(id widget.ListItemID, item fyne.CanvasObject) {
|
||||
c, _ := item.(*widget.Check)
|
||||
im := f.cachedList.Items[id]
|
||||
c.Text = im.Text
|
||||
c.Checked = im.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.cachedList.Items[id].Checked = b
|
||||
f.itemList.Refresh()
|
||||
}
|
||||
c.Refresh()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (f *folderList) initItem(dir string) {
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if file.IsDir() {
|
||||
if file.Name() == ".vscode"||
|
||||
file.Name() == ".svn" {
|
||||
continue
|
||||
}
|
||||
fm := common.Item{
|
||||
Text: file.Name(),
|
||||
Checked: false,
|
||||
}
|
||||
f.cachedList.Items = append(f.cachedList.Items, fm)
|
||||
// f.selItemIds = append(f.selItemIds, fm.Id)
|
||||
f.fileTotal++
|
||||
// logrus.Debugf("%v", fm.Id)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
180
cmd/v2/ui/tool_ping.go
Normal file
180
cmd/v2/ui/tool_ping.go
Normal file
@ -0,0 +1,180 @@
|
||||
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"
|
||||
"net"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/go-ping/ping"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type portStatus struct {
|
||||
port int
|
||||
err string
|
||||
}
|
||||
type appPing struct {
|
||||
appAdapter
|
||||
resultCh chan portStatus
|
||||
}
|
||||
|
||||
func (this *appPing) LazyInit(ptService service.PttService, obs observer.Observer) error {
|
||||
this.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_PING, theme.DownloadIcon(), nil)
|
||||
|
||||
content := container.NewMax()
|
||||
content.Objects = []fyne.CanvasObject{}
|
||||
|
||||
targetHost := widget.NewEntry()
|
||||
targetHost.PlaceHolder = "目标主机Ip"
|
||||
//load
|
||||
storage, _ := os_storage.NewOSStorage()
|
||||
conf, err := storage.LoadConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
portEntry := widget.NewMultiLineEntry()
|
||||
portEntry.Text = "20,21,22,80,1521,2379,2380,3306,6379,8080,8020,8500,9000,9090,13306,50070,27019,10013,8300,8301,8600,10012,10011"
|
||||
saveBtn := widget.NewButton("保存配置", func() {
|
||||
pingConf := &os_storage.PingConf{
|
||||
Host: targetHost.Text,
|
||||
Ports: portEntry.Text,
|
||||
}
|
||||
conf.PingConf = pingConf
|
||||
if err := storage.StoreConfig(conf); err != nil {
|
||||
logrus.WithField("err", err).Debug("保存配置")
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
form := widget.NewForm(
|
||||
widget.NewFormItem("主机", targetHost),
|
||||
widget.NewFormItem("端口", container.NewBorder(nil, nil, nil, saveBtn, portEntry)),
|
||||
)
|
||||
|
||||
if conf.PingConf != nil {
|
||||
targetHost.SetText(conf.PingConf.Host)
|
||||
portEntry.SetText(conf.PingConf.Ports)
|
||||
}
|
||||
// result
|
||||
result := widget.NewMultiLineEntry()
|
||||
result.Disable()
|
||||
|
||||
//初始化端口对应说明字典
|
||||
portDesc := map[int]string{
|
||||
7891: "websocket",
|
||||
10013: "MongoDB",
|
||||
10011: "Redis",
|
||||
10012: "Consul",
|
||||
9567: "gateway",
|
||||
9568: "mainte",
|
||||
9569: "worker",
|
||||
9897: "battle",
|
||||
8001: "cross_mainte",
|
||||
9570: "cross_worker",
|
||||
8000: "web",
|
||||
9571: "cross_web",
|
||||
}
|
||||
|
||||
form.OnSubmit = func() {
|
||||
result.Text = ""
|
||||
if portEntry.Text == "" {
|
||||
return
|
||||
}
|
||||
this.resultCh = make(chan portStatus)
|
||||
ports := strings.Split(portEntry.Text, ",")
|
||||
|
||||
pinger, err := ping.NewPinger(targetHost.Text)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pinger.Count = 3
|
||||
if runtime.GOOS == "windows" {
|
||||
pinger.SetPrivileged(true)
|
||||
}
|
||||
var msgs []string
|
||||
pinger.OnRecv = func(p *ping.Packet) {
|
||||
msgs = append(msgs, fmt.Sprintf("来自:%s 的回复 字节=%d 时间=%dms TTL=%d",
|
||||
p.IPAddr.String(),
|
||||
p.Nbytes,
|
||||
p.Rtt.Milliseconds(),
|
||||
p.Ttl))
|
||||
result.Text = strings.Join(msgs, "\n")
|
||||
result.Refresh()
|
||||
}
|
||||
|
||||
if err := pinger.Run(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
|
||||
ip, err := net.ResolveIPAddr("ip", targetHost.Text)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
this.ping(ip.String(), ports)
|
||||
|
||||
for p := range this.resultCh {
|
||||
desc, ok := portDesc[p.port]
|
||||
if !ok {
|
||||
desc = "未知"
|
||||
}
|
||||
msgs = append(msgs, fmt.Sprintf("%s 端口:%d %s", desc, p.port, p.err))
|
||||
result.Text = strings.Join(msgs, "\n")
|
||||
result.Refresh()
|
||||
}
|
||||
}
|
||||
form.Items[1].HintText = "多个端口使用英文,号分隔"
|
||||
form.SubmitText = "Ping"
|
||||
|
||||
result.OnChanged = func(s string) {
|
||||
result.Refresh()
|
||||
}
|
||||
content.Objects = append(content.Objects, container.NewBorder(form, nil, nil, nil, result))
|
||||
this.tabItem.Content = content
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *appPing) ping(targetHost string, ports []string) {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(ports))
|
||||
for _, port := range ports {
|
||||
go func(p int) {
|
||||
defer wg.Done()
|
||||
_, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", targetHost, p), time.Millisecond*500)
|
||||
var errStr string
|
||||
if err == nil {
|
||||
errStr = "OK"
|
||||
} else {
|
||||
errStr = "ERR"
|
||||
logrus.Error(err)
|
||||
}
|
||||
this.resultCh <- portStatus{port: p, err: errStr}
|
||||
}(cast.ToInt(port))
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer close(this.resultCh)
|
||||
wg.Wait()
|
||||
}()
|
||||
}
|
||||
|
||||
func (a *appPing) GetAppName() string {
|
||||
return common.TOOLBAR_PING
|
||||
}
|
||||
|
||||
func (a *appPing) Icon() fyne.Resource {
|
||||
return theme.ComputerIcon()
|
||||
}
|
788
cmd/v2/ui/tool_term.go
Normal file
788
cmd/v2/ui/tool_term.go
Normal file
@ -0,0 +1,788 @@
|
||||
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
|
||||
}
|
172
cmd/v2/ui/tool_valid.go
Normal file
172
cmd/v2/ui/tool_valid.go
Normal file
@ -0,0 +1,172 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"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"
|
||||
mytheme "go_dreamfactory/cmd/v2/theme"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
fyne_storage "fyne.io/fyne/v2/storage"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type jsonFileList struct {
|
||||
selItemId string //选择的文件ID
|
||||
cachedList common.List
|
||||
itemList *widget.List
|
||||
fileTotal int //文件数
|
||||
|
||||
//字段
|
||||
columnList *widget.List
|
||||
|
||||
}
|
||||
|
||||
func newJsonFileList() *jsonFileList {
|
||||
return &jsonFileList{
|
||||
cachedList: common.NewList(""),
|
||||
}
|
||||
}
|
||||
|
||||
type appConfigValid struct {
|
||||
appAdapter
|
||||
jsonFileList *jsonFileList
|
||||
jsonDirString string //json目录
|
||||
}
|
||||
|
||||
func (a *appConfigValid) LazyInit(pt service.PttService, obs observer.Observer) error {
|
||||
a.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_VALID, mytheme.ResourceExcelJpg, nil)
|
||||
a.jsonFileList = newJsonFileList()
|
||||
|
||||
//load conf
|
||||
storage, _ := os_storage.NewOSStorage()
|
||||
conf, err := storage.LoadConfig()
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if conf.JsonDir != "" {
|
||||
a.jsonDirString = conf.JsonDir
|
||||
}
|
||||
content := container.NewMax()
|
||||
content.Objects = []fyne.CanvasObject{}
|
||||
|
||||
// 打开目录
|
||||
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, _ := fyne_storage.ListerForURI(fyne_storage.NewFileURI("."))
|
||||
dConf.SetLocation(luri)
|
||||
dConf.SetConfirmText("打开")
|
||||
dConf.SetDismissText("取消")
|
||||
dConf.Resize(fyne.NewSize(750, 500))
|
||||
dConf.Show()
|
||||
}
|
||||
//配置json路径
|
||||
jsonDir := widget.NewEntry()
|
||||
jsonDir.PlaceHolder = "json目录"
|
||||
jsonDir.OnChanged = func(s string) {
|
||||
a.jsonFileList.initItem(jsonDir.Text)
|
||||
a.jsonDirString = jsonDir.Text
|
||||
}
|
||||
form := widget.NewForm(
|
||||
widget.NewFormItem("json目录", container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
|
||||
openFolder(jsonDir)
|
||||
a.jsonFileList.initItem(jsonDir.Text)
|
||||
}), jsonDir)),
|
||||
)
|
||||
|
||||
jsonDir.SetText(conf.JsonDir)
|
||||
|
||||
confBtn := &widget.Button{Text: "保存配置", Icon: theme.DocumentCreateIcon()}
|
||||
confBtn.OnTapped = func() {
|
||||
conf.JsonDir = jsonDir.Text
|
||||
|
||||
if err := storage.StoreConfig(conf); err != nil {
|
||||
logrus.WithField("err", err).Debug("保存配置")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 创建json文件 List
|
||||
a.jsonFileList.itemList = a.jsonFileList.createList()
|
||||
|
||||
//创建字段
|
||||
|
||||
c := container.NewBorder(form,
|
||||
container.NewHBox(confBtn),
|
||||
nil, nil,
|
||||
container.NewGridWithColumns(3,
|
||||
container.NewVScroll(a.jsonFileList.itemList)))
|
||||
|
||||
content.Objects = append(content.Objects, c)
|
||||
a.tabItem.Content = content
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *appConfigValid) GetAppName() string {
|
||||
return common.TOOLBAR_VALID
|
||||
}
|
||||
|
||||
func (a *appConfigValid) Icon() fyne.Resource {
|
||||
return mytheme.ResourceExcelJpg
|
||||
}
|
||||
|
||||
func (f *jsonFileList) initItem(dir string) {
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
fileSuffix := path.Ext(file.Name())
|
||||
name := strings.TrimSuffix(file.Name(), fileSuffix)
|
||||
name = strings.TrimPrefix(name, "game_")
|
||||
fm := common.Item{
|
||||
Id: file.Name(),
|
||||
Text: name,
|
||||
Checked: false,
|
||||
}
|
||||
f.cachedList.Items = append(f.cachedList.Items, fm)
|
||||
f.fileTotal++
|
||||
// logrus.Debugf("%v", fm.Id)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *jsonFileList) createList() *widget.List {
|
||||
f.itemList = widget.NewList(
|
||||
func() int {
|
||||
return len(f.cachedList.Items)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return widget.NewLabel("Template")
|
||||
},
|
||||
func(id widget.ListItemID, item fyne.CanvasObject) {
|
||||
c, _ := item.(*widget.Label)
|
||||
c.Text = f.cachedList.Items[id].Text
|
||||
c.Refresh()
|
||||
},
|
||||
)
|
||||
|
||||
f.itemList.OnSelected = func(id widget.ListItemID) {
|
||||
selId := f.cachedList.Items[id].Id
|
||||
f.selItemId = selId
|
||||
return
|
||||
}
|
||||
return f.itemList
|
||||
}
|
63
cmd/v2/ui/tool_welcome.go
Normal file
63
cmd/v2/ui/tool_welcome.go
Normal file
@ -0,0 +1,63 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/cmd/v2/service"
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
|
||||
them "go_dreamfactory/cmd/v2/theme"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/driver/desktop"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type appWelcome struct {
|
||||
appAdapter
|
||||
}
|
||||
|
||||
func (a *appWelcome) LazyInit(service service.PttService, obs observer.Observer) error {
|
||||
logo := canvas.NewImageFromResource(them.ResourceLogoPng)
|
||||
logo.FillMode = canvas.ImageFillContain
|
||||
logo.SetMinSize(fyne.NewSize(362*0.8, 192*0.8))
|
||||
|
||||
a.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_WEL, theme.InfoIcon(), nil)
|
||||
|
||||
wel := widget.NewRichTextFromMarkdown("# " + common.WELCOME_MSG)
|
||||
for i := range wel.Segments {
|
||||
if seg, ok := wel.Segments[i].(*widget.TextSegment); ok {
|
||||
seg.Style.Alignment = fyne.TextAlignCenter
|
||||
}
|
||||
}
|
||||
|
||||
a.tabItem.Content = container.NewCenter(
|
||||
container.NewVBox(
|
||||
wel,
|
||||
logo,
|
||||
// shortCuts,
|
||||
))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *appWelcome) GetAppName() string {
|
||||
return common.TOOLBAR_WEL
|
||||
}
|
||||
|
||||
func (a *appWelcome) OpenDefault() string {
|
||||
return common.TOOLBAR_WEL
|
||||
}
|
||||
|
||||
func (a *appWelcome) ShortCut() fyne.Shortcut {
|
||||
return &desktop.CustomShortcut{KeyName: fyne.Key1, Modifier: fyne.KeyModifierAlt}
|
||||
}
|
||||
|
||||
func (a *appWelcome) Icon() fyne.Resource {
|
||||
return theme.InfoIcon()
|
||||
}
|
||||
|
||||
func (a *appWelcome) OnClose() bool {
|
||||
return false
|
||||
}
|
171
cmd/v2/ui/toolwindow.go
Normal file
171
cmd/v2/ui/toolwindow.go
Normal file
@ -0,0 +1,171 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/cmd/v2/lib/storage"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
mytheme "go_dreamfactory/cmd/v2/theme"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var toolWin *ToolWindowImpl
|
||||
|
||||
type ToolWindow interface {
|
||||
WindowInterface
|
||||
}
|
||||
|
||||
type ToolWindowImpl struct {
|
||||
UIImpl
|
||||
parent fyne.Window
|
||||
w fyne.Window
|
||||
tb *toolBar //工具条
|
||||
sb *statusBar //状态栏
|
||||
at *appContainer //tabs
|
||||
mm *toolMenu //菜单
|
||||
}
|
||||
|
||||
func NewToolWindow(ui *UIImpl, parent fyne.Window) ToolWindow {
|
||||
mw := &ToolWindowImpl{
|
||||
UIImpl: *ui,
|
||||
parent: parent,
|
||||
}
|
||||
|
||||
toolWin = mw
|
||||
|
||||
mw.sb = newStatusBar()
|
||||
|
||||
toolbar := widget.NewToolbar(
|
||||
widget.NewToolbarAction(theme.ContentCopyIcon(), func() {
|
||||
openApp2(mw.at, common.TOOLBAR_GEN)
|
||||
}),
|
||||
|
||||
widget.NewToolbarAction(theme.ContentAddIcon(), func() {
|
||||
openApp2(mw.at, common.TOOLBAR_PB)
|
||||
}),
|
||||
|
||||
widget.NewToolbarAction(theme.DownloadIcon(), func() {
|
||||
openApp2(mw.at, common.TOOLBAR_SEC)
|
||||
}),
|
||||
|
||||
widget.NewToolbarAction(theme.MailSendIcon(), func() {
|
||||
openApp2(mw.at, common.TOOLBAR_TERM)
|
||||
}),
|
||||
|
||||
widget.NewToolbarAction(theme.ComputerIcon(), func() {
|
||||
openApp2(mw.at, common.TOOLBAR_PING)
|
||||
}),
|
||||
|
||||
widget.NewToolbarAction(mytheme.ResourceMongodbJpg, func() {
|
||||
openApp2(mw.at, common.TOOLBAR_MGODB)
|
||||
}),
|
||||
|
||||
widget.NewToolbarAction(mytheme.ResourceExcelJpg, func() {
|
||||
openApp2(mw.at, common.TOOLBAR_VALID)
|
||||
}),
|
||||
|
||||
widget.NewToolbarSpacer(),
|
||||
widget.NewToolbarAction(theme.HelpIcon(), func() {
|
||||
showAbout()
|
||||
}),
|
||||
)
|
||||
|
||||
mw.tb = newToolBar(toolbar)
|
||||
|
||||
mw.at = newAppContainer(toolRegister, nil, ui.obs)
|
||||
|
||||
return mw
|
||||
}
|
||||
|
||||
func (ui *ToolWindowImpl) CreateWindow(title string, width, height float32, _ bool) {
|
||||
w := ui.app.NewWindow(fmt.Sprintf("工具箱 %s %s", title, ui.app.Metadata().Version))
|
||||
ui.AddWindow("tool", w)
|
||||
ui.w = w
|
||||
|
||||
ui.mm = newToolMenu()
|
||||
ui.w.SetMainMenu(ui.mm.MainMenu)
|
||||
// content
|
||||
content := container.NewBorder(ui.tb.toolbar, ui.sb.widget,
|
||||
nil, nil, ui.at)
|
||||
ui.w.SetContent(content)
|
||||
appName, err := ui.at.openWelcome()
|
||||
if err != nil {
|
||||
logrus.WithField("appName", appName).Error(err)
|
||||
}
|
||||
w.Resize(fyne.NewSize(width, height))
|
||||
// w.SetMaster()
|
||||
|
||||
w.Canvas().SetOnTypedKey(func(ke *fyne.KeyEvent) {
|
||||
switch ke.Name {
|
||||
case fyne.KeyEscape:
|
||||
{
|
||||
w.Close()
|
||||
ui.parent.Show()
|
||||
}
|
||||
}
|
||||
})
|
||||
w.CenterOnScreen()
|
||||
w.SetCloseIntercept(func() {
|
||||
ui.parent.Show()
|
||||
w.Close()
|
||||
})
|
||||
w.Show()
|
||||
}
|
||||
func (ui *ToolWindowImpl) quiteHandle() {
|
||||
dialog.ShowConfirm("提示", "确定退出吗", func(b bool) {
|
||||
if !b {
|
||||
return
|
||||
}
|
||||
ui.app.Quit()
|
||||
}, ui.w)
|
||||
}
|
||||
|
||||
func (ui *ToolWindowImpl) syncConfig() {
|
||||
cli := http.Client{Timeout: time.Second * 10}
|
||||
r, err := cli.Get("http://10.0.0.9:8080/prd/config.json")
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
dialog.ShowError(err, ui.w)
|
||||
return
|
||||
}
|
||||
|
||||
defer r.Body.Close()
|
||||
|
||||
b, err2 := ioutil.ReadAll(r.Body)
|
||||
if err2 != nil {
|
||||
logrus.Error(err)
|
||||
dialog.ShowError(err2, ui.w)
|
||||
return
|
||||
}
|
||||
if len(b) == 0 {
|
||||
dialog.ShowError(errors.New("云配置可能不存在"), ui.w)
|
||||
return
|
||||
}
|
||||
config := &storage.Config{}
|
||||
if err := json.Unmarshal(b, config); err != nil {
|
||||
dialog.ShowError(fmt.Errorf("云配置解析错误: %s", err), ui.w)
|
||||
return
|
||||
}
|
||||
|
||||
s, err := storage.NewOSStorage()
|
||||
s.StoreConfig(config)
|
||||
|
||||
dialog.ShowConfirm("提示", "云配置同步成功,需要重新打开窗口", func(b bool) {
|
||||
if !b {
|
||||
return
|
||||
}
|
||||
ui.parent.Show()
|
||||
ui.w.Close()
|
||||
}, ui.w)
|
||||
}
|
72
cmd/v2/ui/toy_datetime.go
Normal file
72
cmd/v2/ui/toy_datetime.go
Normal file
@ -0,0 +1,72 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
"time"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/BabySid/gobase"
|
||||
)
|
||||
|
||||
type toyDateTime struct {
|
||||
toyAdapter
|
||||
date *canvas.Text
|
||||
week *canvas.Text
|
||||
time *canvas.Text
|
||||
}
|
||||
|
||||
func (tdt *toyDateTime) Init(obs observer.Observer) error {
|
||||
tdt.date = canvas.NewText("", nil)
|
||||
tdt.date.TextSize = 15
|
||||
|
||||
tdt.week = canvas.NewText("", nil)
|
||||
tdt.week.TextSize = 15
|
||||
|
||||
tdt.time = canvas.NewText("", nil)
|
||||
tdt.time.TextSize = 42
|
||||
|
||||
tdt.widget = widget.NewCard("", "",
|
||||
container.NewVBox(
|
||||
container.NewHBox(layout.NewSpacer(), tdt.date, tdt.week, layout.NewSpacer()),
|
||||
container.NewCenter(tdt.time),
|
||||
),
|
||||
)
|
||||
|
||||
tdt.widget.Resize(fyne.NewSize(ToyWidth, 110))
|
||||
|
||||
// for init
|
||||
tdt.Run()
|
||||
|
||||
_ = gobase.GlobalScheduler.AddJob("toy_datetime", "*/1 * * * * *", tdt)
|
||||
// todo assert(err == nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
weekStr = [...]string{
|
||||
"Sunday",
|
||||
"Monday",
|
||||
"Tuesday",
|
||||
"Wednesday",
|
||||
"Thursday",
|
||||
"Friday",
|
||||
"Saturday",
|
||||
}
|
||||
)
|
||||
|
||||
func (tdt *toyDateTime) Run() {
|
||||
now := time.Now()
|
||||
|
||||
tdt.date.Text = gobase.FormatTimeStampWithFormat(now.Unix(), gobase.DateFormat)
|
||||
tdt.date.Refresh()
|
||||
|
||||
tdt.week.Text = weekStr[now.Weekday()]
|
||||
tdt.week.Refresh()
|
||||
|
||||
tdt.time.Text = gobase.FormatTimeStampWithFormat(now.Unix(), gobase.TimeFormat)
|
||||
tdt.time.Refresh()
|
||||
}
|
35
cmd/v2/ui/toy_interface.go
Normal file
35
cmd/v2/ui/toy_interface.go
Normal file
@ -0,0 +1,35 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type toyInterface interface {
|
||||
Init(obs observer.Observer) error
|
||||
GetToyCard() *widget.Card
|
||||
}
|
||||
|
||||
var (
|
||||
toyRegister = []toyInterface{
|
||||
&toyDateTime{},
|
||||
&toyUserInfo{},
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
ToyWidth = 250
|
||||
)
|
||||
|
||||
type toyAdapter struct {
|
||||
widget *widget.Card
|
||||
}
|
||||
|
||||
func (t toyAdapter) Init(obs observer.Observer) error {
|
||||
panic("implement Init")
|
||||
}
|
||||
|
||||
func (t toyAdapter) GetToyCard() *widget.Card {
|
||||
return t.widget
|
||||
}
|
321
cmd/v2/ui/toy_userinfo.go
Normal file
321
cmd/v2/ui/toy_userinfo.go
Normal file
@ -0,0 +1,321 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"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/comm"
|
||||
// "go_dreamfactory/modules/user"
|
||||
"go_dreamfactory/pb"
|
||||
"time"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/data/binding"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/atotto/clipboard"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type toyUserInfo struct {
|
||||
toyAdapter
|
||||
|
||||
dataList *widget.List
|
||||
titleLabel *widget.Label
|
||||
|
||||
userInfo *service.UserInfo
|
||||
|
||||
data binding.ExternalStringList
|
||||
obs observer.Observer
|
||||
copyBtn *widget.Button
|
||||
refreshBtn *widget.Button
|
||||
logoutBtn *widget.Button
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) Init(obs observer.Observer) error {
|
||||
this.obs = obs
|
||||
this.titleLabel = widget.NewLabel(common.USERINFO_PANEL_TITLE)
|
||||
this.data = binding.BindStringList(&[]string{})
|
||||
|
||||
// 复制UID button
|
||||
this.copyBtn = widget.NewButtonWithIcon("", theme.ContentCopyIcon(), func() {
|
||||
if this.userInfo != nil && this.userInfo.DbUser != nil {
|
||||
_ = clipboard.WriteAll(this.userInfo.DbUser.Uid)
|
||||
common.ShowTip("已复制UID到剪贴板")
|
||||
}
|
||||
})
|
||||
this.copyBtn.Disable()
|
||||
|
||||
// 刷新
|
||||
this.refreshBtn = widget.NewButtonWithIcon("", theme.ViewRefreshIcon(), func() {
|
||||
if err := service.GetPttService().SendToClient(
|
||||
string("user"),
|
||||
"info",
|
||||
&pb.UserInfoReq{}); err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
})
|
||||
this.refreshBtn.Disable()
|
||||
|
||||
// 注销用户
|
||||
this.logoutBtn = widget.NewButtonWithIcon("", theme.AccountIcon(), func() {
|
||||
// if err := service.GetPttService().SendToClient(
|
||||
// string("user"),
|
||||
// user.UserSubTypeInfo,
|
||||
// &pb.UserInfoReq{}); err != nil {
|
||||
// logrus.Error(err)
|
||||
// return
|
||||
// }
|
||||
})
|
||||
|
||||
// list
|
||||
this.dataList = widget.NewListWithData(this.data,
|
||||
func() fyne.CanvasObject {
|
||||
return widget.NewLabel("template")
|
||||
},
|
||||
func(i binding.DataItem, o fyne.CanvasObject) {
|
||||
o.(*widget.Label).Bind(i.(binding.String))
|
||||
},
|
||||
)
|
||||
|
||||
// md
|
||||
// sign := widget.NewRichTextFromMarkdown(``)
|
||||
// layout
|
||||
this.widget = widget.NewCard("", "",
|
||||
container.NewBorder(container.NewHBox(this.titleLabel, layout.NewSpacer(), this.logoutBtn, this.refreshBtn, this.copyBtn),
|
||||
nil, nil, nil, container.NewVScroll(this.dataList)))
|
||||
this.widget.Resize(fyne.NewSize(ToyWidth, 750))
|
||||
|
||||
this.dataListener()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) dataListener() {
|
||||
this.obs.AddListener(observer.EVENT_USERINFO, observer.Listener{
|
||||
OnNotify: func(d interface{}, args ...interface{}) {
|
||||
time.Sleep(time.Millisecond * 50)
|
||||
_ = this.data.Set([]string{})
|
||||
if this.copyBtn.Disabled() {
|
||||
this.copyBtn.Enable()
|
||||
}
|
||||
if this.refreshBtn.Disabled() {
|
||||
this.refreshBtn.Enable()
|
||||
}
|
||||
this.userInfo = d.(*service.UserInfo)
|
||||
if this.userInfo == nil {
|
||||
return
|
||||
}
|
||||
|
||||
uid = this.userInfo.DbUser.Uid
|
||||
// _ = this.data.Append(fmt.Sprintf("%-3s\t: %s", common.USERINFO_UID, this.userInfo.DbUser.Uid))
|
||||
_ = this.data.Append(this.getAcc()) //0
|
||||
_ = this.data.Append(this.getSid()) //1
|
||||
_ = this.data.Append(this.getName()) //2
|
||||
_ = this.data.Append(this.getAvatar()) //3
|
||||
_ = this.data.Append(this.getVip()) //4
|
||||
_ = this.data.Append(this.getLv()) //5
|
||||
_ = this.data.Append(this.getGold()) //6
|
||||
_ = this.data.Append(this.getExp()) //7
|
||||
_ = this.data.Append(this.getDiamond()) //8
|
||||
_ = this.data.Append(this.getTitle()) //9
|
||||
_ = this.data.Append(this.getActiveDay()) //10
|
||||
_ = this.data.Append(this.getActiveWeek()) //11
|
||||
_ = this.data.Append(this.getFriendPoint()) //12
|
||||
_ = this.data.Append(this.getModiNameCount()) //13
|
||||
_ = this.data.Append(this.getCreateTime())
|
||||
_ = this.data.Append(this.getSign()) //15
|
||||
_ = this.data.Append(this.getBgp()) //16
|
||||
_ = this.data.Append(this.getFigure()) //17
|
||||
_ = this.data.Append(this.getVit()) //18
|
||||
|
||||
this.setProp(2, common.USERINFO_NAME, this.userInfo.DbUser.Name)
|
||||
},
|
||||
})
|
||||
|
||||
this.obs.AddListener(observer.EVENT_REQ_RSP, observer.Listener{
|
||||
OnNotify: func(d interface{}, args ...interface{}) {
|
||||
data := d.(*pb.UserMessage)
|
||||
//change name
|
||||
if data.MainType == string("user") &&
|
||||
data.SubType == "modifyname" {
|
||||
rsp := &pb.UserModifynameResp{}
|
||||
if !comm.ProtoUnmarshal(data, rsp) {
|
||||
logrus.Error("unmarshal err")
|
||||
return
|
||||
}
|
||||
// updatename
|
||||
this.setProp(2, common.USERINFO_NAME, rsp.Name)
|
||||
}
|
||||
|
||||
//update info
|
||||
if data.MainType == string("user") &&
|
||||
data.SubType == "info" {
|
||||
rsp := &pb.UserInfoResp{}
|
||||
if !comm.ProtoUnmarshal(data, rsp) {
|
||||
logrus.Error("unmarshal err")
|
||||
return
|
||||
}
|
||||
|
||||
if rsp.Data == nil {
|
||||
logrus.Debug("没有用户数据返回")
|
||||
}
|
||||
|
||||
this.setProp(1, common.USERINFO_SERVER, rsp.Data.Sid)
|
||||
this.setProp(2, common.USERINFO_NAME, rsp.Data.Name)
|
||||
this.setProp(3, common.USERINFO_AVATAR, rsp.Data.Avatar)
|
||||
this.setProp(4, common.USERINFO_VIP, rsp.Data.Vip)
|
||||
this.setProp(5, common.USERINFO_LV, rsp.Data.Lv)
|
||||
this.setProp(6, common.USERINFO_GOLD, rsp.Data.Gold)
|
||||
this.setProp(7, common.USERINFO_EXP, rsp.Data.Exp)
|
||||
this.setProp(8, common.USERINFO_DIAMOND, rsp.Data.Diamond)
|
||||
this.setProp(9, common.USERINFO_TITLE, rsp.Data.Title)
|
||||
this.setProp(10, common.USERINFO_ACTIVE_DAY, rsp.Ex.Activeday)
|
||||
this.setProp(11, common.USERINFO_ACTIVE_WEEK, rsp.Ex.Activeweek)
|
||||
this.setProp(12, common.USERINFO_FRIENDPOINT, rsp.Ex.FriendPoint)
|
||||
this.setProp(13, common.USERINFO_MODINAME, rsp.Ex.ModifynameCount)
|
||||
this.setProp(13, common.USERINFO_MODINAME, rsp.Ex.ModifynameCount)
|
||||
this.setProp(15, common.USERINFO_SIGN, rsp.Ex.Sign)
|
||||
this.setProp(16, "背景", rsp.Data.Bgp)
|
||||
this.setProp(17, "形象", rsp.Data.Figure)
|
||||
this.setProp(18, "体力", rsp.Data.Ps)
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
this.obs.AddListener(observer.EVENT_USER_CHANGE, observer.Listener{
|
||||
OnNotify: func(d interface{}, args ...interface{}) {
|
||||
data := d.(*model.PushModel)
|
||||
// listener gold
|
||||
if data.Msg.MainType == string("user") &&
|
||||
data.Msg.SubType == "reschange" {
|
||||
rsp := &pb.UserResChangedPush{}
|
||||
if !comm.ProtoUnmarshal(data.Msg, rsp) {
|
||||
logrus.Error("unmarshal err")
|
||||
return
|
||||
}
|
||||
// this.setProp(6, common.USERINFO_GOLD, rsp.Gold)
|
||||
// this.setProp(7, common.USERINFO_EXP, rsp.Exp)
|
||||
// this.setProp(8, common.USERINFO_DIAMOND, rsp.Diamond)
|
||||
}
|
||||
// listener exp
|
||||
// if data.Msg.MainType == string("user") &&
|
||||
// data.Msg.SubType == "" {
|
||||
//TODO change exp
|
||||
// }
|
||||
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) setProp(idx int, label string, val interface{}) {
|
||||
// v, _ := this.data.GetValue(idx)
|
||||
// if v != "" {
|
||||
logrus.WithFields(logrus.Fields{"idx": idx, "lbl": label, "val": val}).Debug("更新Prop")
|
||||
if err := this.data.SetValue(idx, fmt.Sprintf("%-3s\t: %v", label, val)); err != nil {
|
||||
logrus.WithFields(logrus.Fields{"idx": idx, "val": val}).Error(err)
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getAcc() string {
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_ACC, this.userInfo.DbUser.Binduid)
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getSid() string {
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_SERVER, this.userInfo.DbUser.Sid)
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getName() string {
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_NAME, this.userInfo.DbUser.Name)
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getAvatar() string {
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_AVATAR, this.userInfo.DbUser.Avatar)
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getVip() string {
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_VIP, cast.ToString(this.userInfo.DbUser.Vip))
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getLv() string {
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_LV, cast.ToString(this.userInfo.DbUser.Lv))
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getGold() string {
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_GOLD, cast.ToString(this.userInfo.DbUser.Gold))
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getExp() string {
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_EXP, cast.ToString(this.userInfo.DbUser.Exp))
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getDiamond() string {
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_DIAMOND, cast.ToString(this.userInfo.DbUser.Diamond))
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getTitle() string {
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_TITLE, cast.ToString(this.userInfo.DbUser.Exp))
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getFigure() string {
|
||||
return fmt.Sprintf("%-3s\t: %s", "形象", cast.ToString(this.userInfo.DbUser.Figure))
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getBgp() string {
|
||||
return fmt.Sprintf("%-3s\t: %s", "背景", cast.ToString(this.userInfo.DbUser.Bgp))
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getVit() string {
|
||||
return fmt.Sprintf("%-3s\t: %s", "体力", cast.ToString(this.userInfo.DbUser.Ps))
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getActiveDay() string {
|
||||
if this.userInfo.DbUserExpand == nil {
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_ACTIVE_DAY, cast.ToString(0))
|
||||
}
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_ACTIVE_DAY, cast.ToString(this.userInfo.DbUserExpand.Activeday))
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getActiveWeek() string {
|
||||
if this.userInfo.DbUserExpand == nil {
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_ACTIVE_WEEK, cast.ToString(0))
|
||||
}
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_ACTIVE_WEEK, cast.ToString(this.userInfo.DbUserExpand.Activeweek))
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getFriendPoint() string {
|
||||
if this.userInfo.DbUserExpand == nil {
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_FRIENDPOINT, cast.ToString(0))
|
||||
}
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_FRIENDPOINT, cast.ToString(this.userInfo.DbUserExpand.FriendPoint))
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getModiNameCount() string {
|
||||
if this.userInfo.DbUserExpand == nil {
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_MODINAME, "")
|
||||
}
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_MODINAME, cast.ToString(this.userInfo.DbUserExpand.ModifynameCount))
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getSign() string {
|
||||
if this.userInfo.DbUserExpand == nil {
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_SIGN, "")
|
||||
}
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_SIGN, cast.ToString(this.userInfo.DbUserExpand.Sign))
|
||||
}
|
||||
|
||||
func (this *toyUserInfo) getCreateTime() string {
|
||||
ctime := this.userInfo.DbUser.Ctime
|
||||
if ctime <= 0 {
|
||||
return ""
|
||||
}
|
||||
tt := time.Unix(ctime, 0)
|
||||
|
||||
return fmt.Sprintf("%-3s\t: %s", common.USERINFO_CREATETM, tt.Format(time.RFC3339))
|
||||
}
|
31
cmd/v2/ui/toys.go
Normal file
31
cmd/v2/ui/toys.go
Normal file
@ -0,0 +1,31 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
)
|
||||
|
||||
type toys struct {
|
||||
widget *fyne.Container
|
||||
}
|
||||
|
||||
func newToys(obs observer.Observer) *toys {
|
||||
var t toys
|
||||
|
||||
cards := make([]fyne.CanvasObject, len(toyRegister))
|
||||
for i, toy := range toyRegister {
|
||||
toy := toy
|
||||
err := toy.Init(obs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cards[i] = toy.GetToyCard()
|
||||
}
|
||||
|
||||
t.widget = container.New(NewVCZBoxLayout(),
|
||||
cards...)
|
||||
return &t
|
||||
}
|
83
cmd/v2/ui/ui.go
Normal file
83
cmd/v2/ui/ui.go
Normal file
@ -0,0 +1,83 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/lib/storage"
|
||||
"go_dreamfactory/cmd/v2/service"
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
"go_dreamfactory/cmd/v2/theme"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"github.com/BabySid/gobase"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var uid string
|
||||
|
||||
type UI interface {
|
||||
AddWindow(name string, w fyne.Window)
|
||||
Run()
|
||||
Stop()
|
||||
}
|
||||
|
||||
type UIImpl struct {
|
||||
app fyne.App
|
||||
windows map[string]fyne.Window
|
||||
winMux *sync.Mutex
|
||||
connService service.ConnService
|
||||
pttService service.PttService
|
||||
obs observer.Observer
|
||||
storage storage.Storage
|
||||
config *storage.Config
|
||||
}
|
||||
|
||||
func NewUI(app fyne.App,
|
||||
connService service.ConnService,
|
||||
pttService service.PttService,
|
||||
obs observer.Observer,
|
||||
) (*UIImpl, error) {
|
||||
app.Settings().SetTheme(&theme.MyTheme{})
|
||||
|
||||
iStorage, err := storage.NewOSStorage()
|
||||
if err != nil {
|
||||
logrus.Errorf("new storage err:%v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 加载配置
|
||||
config, err := iStorage.LoadConfig()
|
||||
if err != nil {
|
||||
logrus.Errorf("Load config err:%v", err)
|
||||
return nil, err
|
||||
}
|
||||
return &UIImpl{
|
||||
app: app,
|
||||
windows: make(map[string]fyne.Window),
|
||||
winMux: &sync.Mutex{},
|
||||
connService: connService,
|
||||
pttService: pttService,
|
||||
obs: obs,
|
||||
storage: iStorage,
|
||||
config: config,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ui *UIImpl) AddWindow(name string, w fyne.Window) {
|
||||
ui.winMux.Lock()
|
||||
defer ui.winMux.Unlock()
|
||||
ui.windows[name] = w
|
||||
}
|
||||
|
||||
func (ui *UIImpl) Run() {
|
||||
defer func() {
|
||||
_ = os.Unsetenv("FYNE_SCALE")
|
||||
|
||||
gobase.Exit()
|
||||
}()
|
||||
ui.app.Run()
|
||||
}
|
||||
|
||||
func (ui *UIImpl) Stop() {
|
||||
ui.app.Quit()
|
||||
}
|
31
cmd/v2/ui/views/baseformview.go
Normal file
31
cmd/v2/ui/views/baseformview.go
Normal file
@ -0,0 +1,31 @@
|
||||
package formview
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/cmd/v2/service"
|
||||
"go_dreamfactory/cmd/v2/service/observer"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type BaseformView struct {
|
||||
form *widget.Form
|
||||
obs observer.Observer
|
||||
w fyne.Window
|
||||
res *widget.Entry
|
||||
service service.PttService
|
||||
}
|
||||
|
||||
func (view *BaseformView) Init(service service.PttService, obs observer.Observer, w fyne.Window, res *widget.Entry) {
|
||||
view.service = service
|
||||
view.obs = obs
|
||||
view.w = w
|
||||
view.res = res
|
||||
view.form = widget.NewForm()
|
||||
view.form.SubmitText = common.BUTTON_OK
|
||||
}
|
||||
|
||||
func (view *BaseformView) Load() {
|
||||
view.form.OnSubmit()
|
||||
}
|
99
cmd/v2/ui/views/baselistview.go
Normal file
99
cmd/v2/ui/views/baselistview.go
Normal file
@ -0,0 +1,99 @@
|
||||
package formview
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/model"
|
||||
"go_dreamfactory/cmd/v2/service"
|
||||
// "go_dreamfactory/comm"
|
||||
"go_dreamfactory/pb"
|
||||
"go_dreamfactory/utils"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/data/binding"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ListBaseView struct {
|
||||
BaseformView
|
||||
dataListWidget *widget.List
|
||||
dataBinding binding.UntypedList
|
||||
selItemIds []string //选择的ID
|
||||
itemListData *model.ItemModelList
|
||||
}
|
||||
|
||||
// init data
|
||||
func (this *ListBaseView) initItemList() {
|
||||
this.dataBinding = binding.NewUntypedList()
|
||||
this.itemListData = model.NewItemModelList()
|
||||
}
|
||||
|
||||
// create list view with check widget
|
||||
func (this *ListBaseView) createItemListWithCheck() *widget.List {
|
||||
this.dataListWidget = widget.NewListWithData(this.dataBinding,
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewHBox(
|
||||
widget.NewCheck("", func(b bool) {}),
|
||||
widget.NewLabelWithStyle("", fyne.TextAlignCenter, fyne.TextStyle{}),
|
||||
)
|
||||
},
|
||||
func(data binding.DataItem, item fyne.CanvasObject) {
|
||||
o, _ := data.(binding.Untyped).Get()
|
||||
pd := o.(*model.ItemModel)
|
||||
item.(*fyne.Container).Objects[0].(*widget.Check).OnChanged = func(b bool) {
|
||||
if b {
|
||||
this.selItemIds = append(this.selItemIds, pd.Id)
|
||||
} else {
|
||||
utils.DeleteString(this.selItemIds, pd.Id)
|
||||
}
|
||||
}
|
||||
item.(*fyne.Container).Objects[1].(*widget.Label).SetText(pd.Label)
|
||||
},
|
||||
)
|
||||
return this.dataListWidget
|
||||
}
|
||||
|
||||
// create list , single select
|
||||
func (this *ListBaseView) createItemList() *widget.List {
|
||||
this.dataListWidget = widget.NewListWithData(this.dataBinding,
|
||||
func() fyne.CanvasObject {
|
||||
return container.NewHBox(
|
||||
widget.NewLabelWithStyle("", fyne.TextAlignCenter, fyne.TextStyle{}),
|
||||
)
|
||||
},
|
||||
func(data binding.DataItem, item fyne.CanvasObject) {
|
||||
o, _ := data.(binding.Untyped).Get()
|
||||
pd := o.(*model.ItemModel)
|
||||
item.(*fyne.Container).Objects[0].(*widget.Label).SetText(pd.Label)
|
||||
},
|
||||
)
|
||||
|
||||
// single select
|
||||
this.dataListWidget.OnSelected = func(id widget.ListItemID) {
|
||||
sel := this.itemListData.DataList[id]
|
||||
this.selItemIds = []string{sel.Id}
|
||||
}
|
||||
|
||||
return this.dataListWidget
|
||||
}
|
||||
|
||||
func (this *ListBaseView) listBtnFun() func() {
|
||||
return func() {
|
||||
if err := service.GetPttService().SendToClient(
|
||||
string("friend"),
|
||||
// friend.FriendSubTypeApplyList,
|
||||
"",
|
||||
&pb.FriendApplyListReq{}); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
this.itemListData = model.NewItemModelList()
|
||||
}
|
||||
}
|
||||
|
||||
// set data
|
||||
func (this *ListBaseView) reloadListData() {
|
||||
if this.itemListData != nil {
|
||||
d := this.itemListData.AsInterfaceArray()
|
||||
this.dataBinding.Set(d)
|
||||
}
|
||||
}
|
116
cmd/v2/ui/views/bingoview.go
Normal file
116
cmd/v2/ui/views/bingoview.go
Normal file
@ -0,0 +1,116 @@
|
||||
package formview
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/cmd/v2/model"
|
||||
"go_dreamfactory/cmd/v2/service"
|
||||
"go_dreamfactory/pb"
|
||||
"strings"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type BingoView struct {
|
||||
BaseformView
|
||||
}
|
||||
|
||||
func (this *BingoView) CreateView(t *model.TestCase) fyne.CanvasObject {
|
||||
var (
|
||||
gridContainer *fyne.Container
|
||||
ttxt string //T text
|
||||
aSel *widget.Select
|
||||
)
|
||||
|
||||
tEntry := widget.NewEntry()
|
||||
tEntry.PlaceHolder = "配置ID"
|
||||
tEntry.OnChanged = func(s string) {
|
||||
ttxt = s
|
||||
}
|
||||
|
||||
nEntry := widget.NewEntry()
|
||||
nEntry.PlaceHolder = "数量"
|
||||
|
||||
attrSel := &widget.Select{}
|
||||
attrSel.Options = []string{"选择", "gold", "diamond", "exp", "moongold", "friendPoint", "ps", "guildcoin", "arenacoin", "merchantmoney"}
|
||||
attrSel.SetSelected("选择")
|
||||
attrSel.OnChanged = func(s string) {
|
||||
ttxt = s
|
||||
}
|
||||
|
||||
aSel = &widget.Select{}
|
||||
gridContainer = container.NewGridWithColumns(3, aSel, tEntry, nEntry)
|
||||
|
||||
aSel.Options = []string{"选择", "attr", "item", "hero", "equi", "mapid", "pataid", "alltask", "worldtask", "sociatyexp", "sociatyactivity", "allgrowtask", "lv"}
|
||||
aSel.SetSelected("选择")
|
||||
aSel.OnChanged = func(s string) {
|
||||
if s == "attr" {
|
||||
gridContainer.Objects[1] = attrSel
|
||||
ttxt = attrSel.Selected
|
||||
} else {
|
||||
gridContainer.Objects[1] = tEntry
|
||||
ttxt = tEntry.Text
|
||||
}
|
||||
}
|
||||
|
||||
this.form.AppendItem(widget.NewFormItem(common.APP_TESTCASE_FORM_BINGO, gridContainer))
|
||||
|
||||
this.form.OnSubmit = func() {
|
||||
var bingo string
|
||||
if ttxt == "" && nEntry.Text == "" {
|
||||
bingo = fmt.Sprintf("bingo:%s", aSel.Selected)
|
||||
} else if ttxt != "" && nEntry.Text == "" {
|
||||
bingo = fmt.Sprintf("bingo:%s,%s", aSel.Selected, ttxt)
|
||||
} else if ttxt == "" && nEntry.Text != "" {
|
||||
bingo = fmt.Sprintf("bingo:%s,%s", aSel.Selected, nEntry.Text)
|
||||
} else if ttxt != "" && nEntry.Text != "" {
|
||||
bingo = fmt.Sprintf("bingo:%s,%s,%s", aSel.Selected, ttxt, nEntry.Text)
|
||||
}
|
||||
logrus.Info(bingo)
|
||||
if aSel.Selected == "选择" || nEntry.Text == "0" {
|
||||
dialog.ShowError(errors.New("请填写完整且正确的数值"), this.w)
|
||||
return
|
||||
}
|
||||
if err := service.GetPttService().SendToClient(
|
||||
t.MainType,
|
||||
t.SubType,
|
||||
&pb.GMCmdReq{Cmod: bingo},
|
||||
); err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
aSel.SetSelected("")
|
||||
attrSel.SetSelected("")
|
||||
nEntry.SetText("")
|
||||
tEntry.SetText("")
|
||||
}
|
||||
|
||||
bingoEntry := widget.NewEntry()
|
||||
bingoEntry.PlaceHolder = "bingo:item,10001,1"
|
||||
|
||||
customForm := widget.NewForm(widget.NewFormItem("自定义", bingoEntry))
|
||||
customForm.OnSubmit = func() {
|
||||
if bingoEntry.Text == "" || !strings.HasPrefix(bingoEntry.Text, "bingo:") {
|
||||
dialog.ShowError(errors.New("请填写完整并加上bingo:前缀"), this.w)
|
||||
return
|
||||
}
|
||||
if err := service.GetPttService().SendToClient(
|
||||
t.MainType,
|
||||
t.SubType,
|
||||
&pb.GMCmdReq{Cmod: bingoEntry.Text},
|
||||
); err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
customForm.SubmitText = common.BUTTON_OK
|
||||
|
||||
c := container.NewVBox(this.form, customForm)
|
||||
return c
|
||||
}
|
67
cmd/v2/ui/views/checkworldtask.go
Normal file
67
cmd/v2/ui/views/checkworldtask.go
Normal file
@ -0,0 +1,67 @@
|
||||
package formview
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
"go_dreamfactory/cmd/v2/model"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
|
||||
cfg "go_dreamfactory/sys/configure/structs"
|
||||
)
|
||||
|
||||
// 世界任务检查
|
||||
type CheckWorldtaskView struct {
|
||||
BaseformView
|
||||
taskList *common.ItemList //世界任务执行过程列表
|
||||
}
|
||||
|
||||
// - 检查世界任务状态
|
||||
// 1. 输入任务ID 查询 任务状态
|
||||
// 2. 查询所有任务执行结果
|
||||
|
||||
// - 模拟世界任务流程
|
||||
// 1.根据配置自动执行所有流程
|
||||
// 2.输出每个任务执行过程(文件)
|
||||
// 3.如果有异常,输出执行错误原因
|
||||
func (view *CheckWorldtaskView) CreateView(t *model.TestCase) fyne.CanvasObject {
|
||||
//taskId entry
|
||||
// taskId:= widget.NewEntry()
|
||||
|
||||
//输出每个任务执行过程(文件)
|
||||
path := widget.NewEntry()
|
||||
jsonPathEntry := widget.NewEntry()
|
||||
des := widget.NewEntry()
|
||||
mockForm := widget.NewForm(
|
||||
widget.NewFormItem("任务类型", des),
|
||||
widget.NewFormItem("Json配置", jsonPathEntry),
|
||||
widget.NewFormItem("结果目录", path),
|
||||
)
|
||||
|
||||
view.taskList = common.NewItemList()
|
||||
|
||||
view.taskList.ItemList = view.taskList.CreateList()
|
||||
|
||||
helpBtn := widget.NewButtonWithIcon("", theme.HelpIcon(), func() {})
|
||||
mockBtn := widget.NewButton("模拟执行", func() {
|
||||
commCfg := &common.Config{
|
||||
Path: jsonPathEntry.Text,
|
||||
}
|
||||
// 读取配置
|
||||
if tb, err := cfg.NewTables(commCfg.Loader); err == nil {
|
||||
tb.WorldTask.GetDataList()
|
||||
}
|
||||
// 读取协议
|
||||
// 设置协议参数
|
||||
// 输出结果
|
||||
})
|
||||
top := container.NewHBox()
|
||||
bottom := container.NewHBox(helpBtn, mockBtn)
|
||||
c := container.NewBorder(top, nil, nil, nil, view.taskList.ItemList)
|
||||
layout := container.NewVSplit(
|
||||
container.NewBorder(nil, bottom, nil, nil, container.NewGridWithColumns(2, mockForm)), c)
|
||||
layout.Offset = 0.2
|
||||
return layout
|
||||
}
|
31
cmd/v2/ui/views/common.go
Normal file
31
cmd/v2/ui/views/common.go
Normal file
@ -0,0 +1,31 @@
|
||||
package formview
|
||||
|
||||
import (
|
||||
"go_dreamfactory/cmd/v2/lib/common"
|
||||
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
// 获取任务标签
|
||||
func getTaskTagSelect() *widget.Select {
|
||||
var tagSelect *widget.Select
|
||||
tagSelect = widget.NewSelect([]string{
|
||||
common.AAP_TESTCASE_FORM_TASK_DAY,
|
||||
common.APP_TESTCASE_FORM_TASK_WEEK,
|
||||
common.APP_TESTCASE_FORM_TASK_ACHIEVE}, func(s string) {
|
||||
switch s {
|
||||
case common.AAP_TESTCASE_FORM_TASK_DAY:
|
||||
tagSelect.Selected = "1"
|
||||
case common.APP_TESTCASE_FORM_TASK_WEEK:
|
||||
tagSelect.Selected = "2"
|
||||
case common.APP_TESTCASE_FORM_TASK_ACHIEVE:
|
||||
tagSelect.Selected = "3"
|
||||
default:
|
||||
tagSelect.Selected = "0"
|
||||
}
|
||||
|
||||
})
|
||||
tagSelect.SetSelectedIndex(0)
|
||||
return tagSelect
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user