diff --git a/cmd/v2/configure/structs/Game.TestFlow.go b/cmd/v2/configure/structs/Game.TestFlow.go
new file mode 100644
index 000000000..b8946f191
--- /dev/null
+++ b/cmd/v2/configure/structs/Game.TestFlow.go
@@ -0,0 +1,42 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+package cfg
+
+type GameTestFlow struct {
+ _dataMap map[int32]*GameTestFlowData
+ _dataList []*GameTestFlowData
+}
+
+func NewGameTestFlow(_buf []map[string]interface{}) (*GameTestFlow, error) {
+ _dataList := make([]*GameTestFlowData, 0, len(_buf))
+ dataMap := make(map[int32]*GameTestFlowData)
+ for _, _ele_ := range _buf {
+ if _v, err2 := DeserializeGameTestFlowData(_ele_); err2 != nil {
+ return nil, err2
+ } else {
+ _dataList = append(_dataList, _v)
+ dataMap[_v.Id] = _v
+ }
+ }
+ return &GameTestFlow{_dataList:_dataList, _dataMap:dataMap}, nil
+}
+
+func (table *GameTestFlow) GetDataMap() map[int32]*GameTestFlowData {
+ return table._dataMap
+}
+
+func (table *GameTestFlow) GetDataList() []*GameTestFlowData {
+ return table._dataList
+}
+
+func (table *GameTestFlow) Get(key int32) *GameTestFlowData {
+ return table._dataMap[key]
+}
+
+
diff --git a/cmd/v2/configure/structs/Game.TestFlowData.go b/cmd/v2/configure/structs/Game.TestFlowData.go
new file mode 100644
index 000000000..c41d92c1a
--- /dev/null
+++ b/cmd/v2/configure/structs/Game.TestFlowData.go
@@ -0,0 +1,41 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+package cfg
+
+import "errors"
+
+type GameTestFlowData struct {
+ Id int32
+ Msg string
+ Route string
+ Params string
+}
+
+const TypeId_GameTestFlowData = -1087831770
+
+func (*GameTestFlowData) GetTypeId() int32 {
+ return -1087831770
+}
+
+func (_v *GameTestFlowData)Deserialize(_buf map[string]interface{}) (err error) {
+ { var _ok_ bool; var _tempNum_ float64; if _tempNum_, _ok_ = _buf["id"].(float64); !_ok_ { err = errors.New("id error"); return }; _v.Id = int32(_tempNum_) }
+ { var _ok_ bool; if _v.Msg, _ok_ = _buf["msg"].(string); !_ok_ { err = errors.New("msg error"); return } }
+ { var _ok_ bool; if _v.Route, _ok_ = _buf["route"].(string); !_ok_ { err = errors.New("route error"); return } }
+ { var _ok_ bool; if _v.Params, _ok_ = _buf["params"].(string); !_ok_ { err = errors.New("params error"); return } }
+ return
+}
+
+func DeserializeGameTestFlowData(_buf map[string]interface{}) (*GameTestFlowData, error) {
+ v := &GameTestFlowData{}
+ if err := v.Deserialize(_buf); err == nil {
+ return v, nil
+ } else {
+ return nil, err
+ }
+}
diff --git a/cmd/v2/configure/structs/Tables.go b/cmd/v2/configure/structs/Tables.go
new file mode 100644
index 000000000..077e3ee0a
--- /dev/null
+++ b/cmd/v2/configure/structs/Tables.go
@@ -0,0 +1,31 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+package cfg
+
+type JsonLoader func(string) ([]map[string]interface{}, error)
+
+type Tables struct {
+ TestFlow *GameTestFlow
+}
+
+func NewTables(loader JsonLoader) (*Tables, error) {
+ var err error
+ var buf []map[string]interface{}
+
+ tables := &Tables{}
+
+ if buf, err = loader("game_testflow") ; err != nil {
+ return nil, err
+ }
+ if tables.TestFlow, err = NewGameTestFlow(buf) ; err != nil {
+ return nil, err
+ }
+
+ return tables, nil
+}
diff --git a/cmd/v2/game_testflow.json b/cmd/v2/game_testflow.json
new file mode 100644
index 000000000..ddd783702
--- /dev/null
+++ b/cmd/v2/game_testflow.json
@@ -0,0 +1,44 @@
+[
+ {
+ "id": 1,
+ "msg": "功能列表",
+ "route": "sys.funclist",
+ "params": "{}"
+ },
+ {
+ "id": 2,
+ "msg": "",
+ "route": "",
+ "params": ""
+ },
+ {
+ "id": 3,
+ "msg": "",
+ "route": "",
+ "params": ""
+ },
+ {
+ "id": 4,
+ "msg": "",
+ "route": "",
+ "params": ""
+ },
+ {
+ "id": 5,
+ "msg": "",
+ "route": "",
+ "params": ""
+ },
+ {
+ "id": 6,
+ "msg": "",
+ "route": "",
+ "params": ""
+ },
+ {
+ "id": 7,
+ "msg": "",
+ "route": "",
+ "params": ""
+ }
+]
\ No newline at end of file
diff --git a/cmd/v2/lib/assistant.go b/cmd/v2/lib/assistant.go
new file mode 100644
index 000000000..b7ebb9935
--- /dev/null
+++ b/cmd/v2/lib/assistant.go
@@ -0,0 +1,255 @@
+package lib
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "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 //调用结果
+}
+
+func NewAssistant(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,
+ }
+ if err := a.init(); err != nil {
+ return nil, err
+ }
+ return a, nil
+}
+
+func (a *assistant) init() error {
+ logrus.Info("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).Info("AI助手初始化完成 并发量 ")
+ return nil
+}
+
+func (a *assistant) callOne(req *RawReq) *RawResp {
+ atomic.AddInt64(&a.callCount, 1)
+ if req == nil {
+ return &RawResp{ID: -1, Err: errors.New("无效的请求")}
+ }
+ var rawResp RawResp
+ start := time.Now().UnixNano()
+ resp, err := a.caller.Call(req.Req, a.timeout)
+ 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() {
+ a.goPool.Return()
+ }()
+
+ req := a.caller.BuildReq()
+ //调用状态 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.Info("关闭结果通道")
+ close(a.resultCh)
+ atomic.StoreUint32(&a.status, STATUS_STOPPED)
+}
+
+// 发送请求即调用接口
+func (a *assistant) handleReq(tick <-chan time.Time) {
+ for {
+ select {
+ case <-a.ctx.Done():
+ a.prepareStop(a.ctx.Err())
+ return
+ default:
+ }
+ a.asyncCall()
+ if a.lps > 0 {
+ select {
+ case <-tick:
+ case <-a.ctx.Done():
+ a.prepareStop(a.ctx.Err())
+ return
+ }
+ }
+ }
+}
+
+func (a *assistant) sendResult(result *CallResult) bool {
+ if atomic.LoadUint32(&a.status) != STATUS_STARTED {
+ return false
+ }
+ select {
+ case a.resultCh <- result:
+ return true
+ default:
+ return false
+ }
+}
+
+//注册账号
+func (a *assistant) registUser() {
+
+}
+
+//登录账号
+func (a *assistant) login() {
+
+}
+
+// 启动AI助手
+func (a *assistant) Start() bool {
+ logrus.Infoln("AI助手启动")
+
+ // 节流 周期性向目标发送
+ var ticker <-chan time.Time
+ if a.lps > 0 {
+ //间隔时间
+ interval := time.Duration(1e9 / a.lps)
+ logrus.Infof("启动节流控制 间隔: %v", interval)
+ ticker = 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.Infoln("请求处理...")
+ a.handleReq(ticker)
+ logrus.Infof("停止 调用次数:%d", a.callCount)
+ }()
+
+ return true
+}
+
+// 手动停止
+func (a *assistant) Stop() error {
+ return nil
+}
+
+func (a *assistant) ShowResult() {
+
+ 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
+ }
+ logrus.WithFields(logrus.Fields{"mainType": msg.MainType, "subType": msg.SubType}).Debug("读取结果")
+ }
+}
diff --git a/cmd/v2/lib/base.go b/cmd/v2/lib/base.go
new file mode 100644
index 000000000..96836b094
--- /dev/null
+++ b/cmd/v2/lib/base.go
@@ -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
+)
diff --git a/cmd/v2/lib/common/constant.go b/cmd/v2/lib/common/constant.go
index e7a7e56a2..cdd9ecfe0 100644
--- a/cmd/v2/lib/common/constant.go
+++ b/cmd/v2/lib/common/constant.go
@@ -6,6 +6,12 @@ type (
WindowAction int64
)
+const (
+ MainType = "mainType"
+ SubType = "subType"
+ Params = "params"
+)
+
const (
WindowAspect_Normal WindowAspect = iota
WindowAspect_FullScreen
diff --git a/cmd/v2/lib/common/lang.go b/cmd/v2/lib/common/lang.go
index bb0f3ed4b..462fe4eec 100644
--- a/cmd/v2/lib/common/lang.go
+++ b/cmd/v2/lib/common/lang.go
@@ -71,6 +71,7 @@ package common
// zh
const (
APP_NAME = "机器人"
+
// app 子标题 [0.0.1 build-1] 应用名称
APP_WIN_TITLE = "%s [%s build-%d] %s"
WELCOME_MSG = "欢迎使用工具箱"
@@ -94,6 +95,11 @@ const (
TOOLBAR_WEL = "欢迎"
TOOLBAR_TERM = "同步配置"
TOOLBAR_PB = "protobuf"
+ TOOLBAR_AUTO = "自动化"
+
+ TOOLBAR_PERF_TIP = "使用说明"
+ TOOLBAR_PERF_CONF = "配置"
+ TOOLBAR_PERF_PB = "协议"
//monitor
APP_MONITOR_TITLE_ID = "编号"
diff --git a/cmd/v2/lib/common/log.go b/cmd/v2/lib/common/log.go
new file mode 100644
index 000000000..8bc99cdff
--- /dev/null
+++ b/cmd/v2/lib/common/log.go
@@ -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"`
+}
diff --git a/cmd/v2/lib/common/utils.go b/cmd/v2/lib/common/utils.go
index b524d658e..9afc4134d 100644
--- a/cmd/v2/lib/common/utils.go
+++ b/cmd/v2/lib/common/utils.go
@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"io"
+ "io/ioutil"
"math"
"os"
"path/filepath"
@@ -156,3 +157,15 @@ func ConvertFileSize(size int64) string {
return "0"
}
+
+func Loader(file string) ([]map[string]interface{}, error) {
+ if bytes, err := ioutil.ReadFile("./" + file + ".json"); 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
+ }
+}
diff --git a/cmd/v2/lib/core.go b/cmd/v2/lib/core.go
new file mode 100644
index 000000000..be87da718
--- /dev/null
+++ b/cmd/v2/lib/core.go
@@ -0,0 +1,7 @@
+package lib
+
+type Aiassistant interface {
+ Start() bool
+ Stop() error
+ ShowResult()
+}
diff --git a/cmd/v2/lib/gopool.go b/cmd/v2/lib/gopool.go
new file mode 100644
index 000000000..8cd894a54
--- /dev/null
+++ b/cmd/v2/lib/gopool.go
@@ -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))
+}
diff --git a/cmd/v2/lib/handler.go b/cmd/v2/lib/handler.go
new file mode 100644
index 000000000..34db1c27d
--- /dev/null
+++ b/cmd/v2/lib/handler.go
@@ -0,0 +1,23 @@
+package lib
+
+import "time"
+
+// 处理器接口
+type Handler interface {
+ // 处理请求
+ BuildReq() RawReq
+ //调用
+ Call(req []byte, timeoutNS time.Duration) ([]byte, error)
+ // 检查响应
+ Check(req RawReq, rsp RawResp) *CallResult
+}
+
+// 调用结果
+type CallResult struct {
+ Id int64
+ Req RawReq
+ Resp RawResp
+ Code ResCode
+ Message string
+ Elapse time.Duration
+}
diff --git a/cmd/v2/lib/param.go b/cmd/v2/lib/param.go
new file mode 100644
index 000000000..76c6d7aaf
--- /dev/null
+++ b/cmd/v2/lib/param.go
@@ -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("通过. (timeoutNS=%s, lps=%d, durationNS=%s)",
+ param.Timeout, param.Lps, param.Duration))
+ logrus.Infoln(buf.String())
+ return nil
+}
diff --git a/cmd/v2/lib/storage/config.go b/cmd/v2/lib/storage/config.go
new file mode 100644
index 000000000..759770ce0
--- /dev/null
+++ b/cmd/v2/lib/storage/config.go
@@ -0,0 +1,26 @@
+package storage
+
+//默认配置
+func newDefaultConfig() *Config {
+ return &Config{
+ Pressure: PressureConfig{
+ TimeoutMs: 50,
+ Concurrency: 10,
+ DurationS: 5,
+ },
+ UserCount: 100,
+ }
+}
+
+type Config struct {
+ Pressure PressureConfig `json:"Pressure,omitempty"`
+ UserCount int32 `json:"UserCount,omitempty"` //用户数
+ WsAddr string `json:"wsAddr,omitempty"` //websocket addr
+}
+
+//压测配置
+type PressureConfig struct {
+ TimeoutMs int32 `json:"timeout,omitempty"` //超时时间 毫秒
+ Concurrency int32 `json:"concurrency,omitempty"` //并发量
+ DurationS int32 `json:"duration,omitempty"` //持续时间 秒
+}
diff --git a/cmd/v2/lib/storage/storage.go b/cmd/v2/lib/storage/storage.go
new file mode 100644
index 000000000..3b9a68fbd
--- /dev/null
+++ b/cmd/v2/lib/storage/storage.go
@@ -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)
+}
diff --git a/cmd/v2/lib/storage/storage_os.go b/cmd/v2/lib/storage/storage_os.go
new file mode 100644
index 000000000..f363b41fd
--- /dev/null
+++ b/cmd/v2/lib/storage/storage_os.go
@@ -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
+}
diff --git a/cmd/v2/main.go b/cmd/v2/main.go
index 71d718cd1..feaf4ba7d 100644
--- a/cmd/v2/main.go
+++ b/cmd/v2/main.go
@@ -8,6 +8,7 @@ import (
"go_dreamfactory/cmd/v2/service/observer"
"go_dreamfactory/cmd/v2/theme"
"go_dreamfactory/cmd/v2/ui"
+ "image/color"
"io"
"log"
"os"
@@ -17,6 +18,7 @@ import (
"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"
@@ -67,7 +69,13 @@ func main() {
// create a new ui
app := app.NewWithID("df-toolkit")
app.SetIcon(theme.ResourceAppPng)
- appUI := ui.NewUI(app, configService, connService, pttService, obs)
+
+ appUI, err := ui.NewUI(app, configService, 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
@@ -78,7 +86,7 @@ func main() {
checkVersion(app, w)
}
- w.SetContent(container.NewGridWithColumns(2,
+ w.SetContent(container.NewGridWithColumns(3,
widget.NewButton("工具", func() {
toolWindow := ui.NewToolWindow(appUI, w)
toolWindow.CreateWindow(common.APP_NAME, 1499, 800, true)
@@ -88,7 +96,13 @@ func main() {
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, 600, 800, true)
+ w.Hide()
+ }),
+ ))
w.SetFixedSize(true)
w.Resize(fyne.NewSize(400, 200))
w.CenterOnScreen()
@@ -96,7 +110,7 @@ func main() {
app.Quit()
})
- logrus.WithField("version", app.Metadata().Version).Info("app starting")
+ logrus.WithField("version", app.Metadata().Version).Debug("app starting")
w.Show()
appUI.Run()
}
@@ -144,12 +158,13 @@ func setupConfig() (err error) {
}
func setupLogger() (err error) {
- logrus.SetFormatter(&logrus.TextFormatter{
- DisableColors: true,
- FullTimestamp: true,
+ logrus.SetFormatter(&logrus.JSONFormatter{
+ TimestampFormat: "2006-01-02 15:04:05",
+ // DisableColors: true,
+ // FullTimestamp: true,
})
- logrus.SetLevel(logrus.DebugLevel)
+ logrus.SetLevel(logrus.InfoLevel)
logrus.SetOutput(os.Stdout)
//设置output,默认为stderr,可以为任何io.Writer,比如文件*os.File
diff --git a/cmd/v2/resources/config.yaml b/cmd/v2/resources/config.yaml
index a1f10234a..2dfa47a48 100644
--- a/cmd/v2/resources/config.yaml
+++ b/cmd/v2/resources/config.yaml
@@ -7,7 +7,7 @@ services:
- service:
sid: "dfz"
name: 赵长远
- url: ws://10.0.0.238:7891/gateway
+ url: ws://10.0.5.145:7891/gateway
- service:
sid: "df01"
name: 内网
diff --git a/cmd/v2/service/assistant_test.go b/cmd/v2/service/assistant_test.go
new file mode 100644
index 000000000..c6ad4680f
--- /dev/null
+++ b/cmd/v2/service/assistant_test.go
@@ -0,0 +1,28 @@
+package service
+
+import (
+ "go_dreamfactory/cmd/v2/lib"
+ "testing"
+ "time"
+)
+
+func TestStart(t *testing.T) {
+ wsAddr := "ws://10.0.5.215:7891/gateway"
+ param := lib.ParamMgr{
+ Caller: NewWsCli(wsAddr),
+ Timeout: 2 * time.Second,
+ Lps: uint32(10),
+ Duration: 3 * time.Second,
+ ResultCh: make(chan *lib.CallResult, 50),
+ }
+ a, err := lib.NewAssistant(param)
+ if err != nil {
+ t.Fatalf("AI助手初始化错误: %v", err)
+ t.FailNow()
+ }
+
+ t.Log("AI助手启动...")
+ a.Start()
+
+ a.ShowResult()
+}
diff --git a/cmd/v2/service/pttService.go b/cmd/v2/service/pttService.go
index 12db6a407..d03dd5b8a 100644
--- a/cmd/v2/service/pttService.go
+++ b/cmd/v2/service/pttService.go
@@ -71,14 +71,17 @@ func (p *PttServiceImpl) SendToClient(mainType, subType string, rsp proto.Messag
func (p *PttServiceImpl) Login(sid, account string) (code pb.ErrorCode) {
head := &pb.UserMessage{MainType: string(comm.ModuleUser), SubType: user.UserSubTypeLogin}
head.Sec = common.BuildSecStr(sid, account)
- if err := p.connService.SendMsg(head, &pb.UserLoginReq{
+ req := &pb.UserLoginReq{
Account: account,
Sid: sid,
- }); err != nil {
+ }
+ if err := p.connService.SendMsg(head, req); err != nil {
code = pb.ErrorCode_SystemError
logrus.WithField("err", err).Error("Login")
return
}
+ logrus.WithFields(logrus.Fields{common.MainType: string(comm.ModuleUser), common.SubType: user.UserSubTypeLogin,
+ common.Params: req}).Info("登录")
return
}
diff --git a/cmd/v2/service/wsCli.go b/cmd/v2/service/wsCli.go
new file mode 100644
index 000000000..6b0e7bf2e
--- /dev/null
+++ b/cmd/v2/service/wsCli.go
@@ -0,0 +1,160 @@
+package service
+
+import (
+ "go_dreamfactory/cmd/v2/lib/common"
+ "go_dreamfactory/cmd/v2/lib"
+ "go_dreamfactory/comm"
+ "go_dreamfactory/pb"
+ "strings"
+ "time"
+
+ "github.com/Pallinder/go-randomdata"
+ "github.com/gorilla/websocket"
+ "github.com/sirupsen/logrus"
+ "google.golang.org/protobuf/proto"
+)
+
+type WsCli struct {
+ addr string
+}
+
+func NewWsCli(addr string) lib.Handler {
+ return &WsCli{addr: addr}
+}
+
+func (cli *WsCli) 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 (cli *WsCli) checkLoginResp(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("登录响应")
+ return true
+ }
+ }
+ 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" {
+ logrus.WithField("methodName", methodName).Debug("收到错误码")
+ } else {
+ logrus.WithField("methodName", methodName).Debug("收到推送")
+ }
+ return true
+ }
+ return false
+}
+
+func (cli *WsCli) BuildReq() lib.RawReq {
+ id := time.Now().UnixNano()
+
+ // TODO: 读流程表配置,确定请求UserMessage
+ b, err := cli.loginReq()
+ if err != nil {
+ panic(err)
+ }
+ rawReq := lib.RawReq{ID: id, Req: b}
+ return rawReq
+}
+
+func (cli *WsCli) Call(req []byte, timeout time.Duration) ([]byte, error) {
+ dialer := &websocket.Dialer{
+ HandshakeTimeout: timeout,
+ }
+ conn, _, err := dialer.Dial(cli.addr, nil)
+ if err != nil {
+ logrus.Errorf("websocket conn err:%v", err)
+ return nil, err
+ }
+
+ go func() {
+ timer := time.NewTimer(2 * time.Second)
+ for {
+ timer.Reset(2 * time.Second)
+ <-timer.C
+ if err := conn.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
+ break
+ }
+ }
+ }()
+
+ // 向连接写数据
+ 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.checkLoginResp(data) {
+ return data,nil
+ } else {
+ if !cli.checkPush(data) {
+ logrus.Debug("登录失败")
+ }
+ }
+ }
+
+ 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
+ //TODO 解析结果
+ 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
+}
diff --git a/cmd/v2/ui/app_auto.go b/cmd/v2/ui/app_auto.go
new file mode 100644
index 000000000..599c78482
--- /dev/null
+++ b/cmd/v2/ui/app_auto.go
@@ -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()
+}
diff --git a/cmd/v2/ui/app_container.go b/cmd/v2/ui/app_container.go
index db11238fb..c3657aa95 100644
--- a/cmd/v2/ui/app_container.go
+++ b/cmd/v2/ui/app_container.go
@@ -61,10 +61,10 @@ func (at *appContainer) openApp(app appInterface) error {
}
// open default app
-func (at *appContainer) openDefaultApp() (string, error) {
+func (at *appContainer) openDefaultApp(appName string) (string, error) {
var firstTab *container.TabItem
for _, app := range at.ai {
- if app.OpenDefault() {
+ if app.OpenDefault() == appName {
if err := at.initApp(app); err != nil {
return app.GetAppName(), err
}
diff --git a/cmd/v2/ui/app_interface.go b/cmd/v2/ui/app_interface.go
index 528467a31..46543ec0c 100644
--- a/cmd/v2/ui/app_interface.go
+++ b/cmd/v2/ui/app_interface.go
@@ -4,34 +4,47 @@ 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() bool
+ OpenDefault() string
+ GetUI() interface{}
OnClose() bool
+ ShortCut() fyne.Shortcut
+ Icon() fyne.Resource
}
var (
appRegister = []appInterface{
&appMonitor{},
&appTester{},
- }
+ &appAuto{},
- toolRegister = []appInterface{
&appWelcome{},
&appGen{},
&appPbGen{},
&appLock{},
&appTerm{},
+
+ &perfWelcome{},
+ &perfConf{},
+ &perfPb{},
}
)
type appAdapter struct {
tabItem *container.TabItem
+ ai []appInterface
+}
+
+func (a appAdapter) ShortCut() fyne.Shortcut {
+ panic("implement Shortcut")
}
func (a appAdapter) LazyInit() error {
@@ -42,8 +55,12 @@ func (a appAdapter) GetAppName() string {
panic("implement GetAppName()")
}
-func (a appAdapter) OpenDefault() bool {
- return false
+func (a appAdapter) GetUI() interface{} {
+ panic("implement GetUI()")
+}
+
+func (a appAdapter) OpenDefault() string {
+ return ""
}
func (a appAdapter) GetTabItem() *container.TabItem {
@@ -53,3 +70,7 @@ func (a appAdapter) GetTabItem() *container.TabItem {
func (a appAdapter) OnClose() bool {
return true
}
+
+func (a appAdapter) Icon() fyne.Resource {
+ return theme.FyneLogo()
+}
diff --git a/cmd/v2/ui/app_monitor.go b/cmd/v2/ui/app_monitor.go
index 664f2f6e3..73d73a91b 100644
--- a/cmd/v2/ui/app_monitor.go
+++ b/cmd/v2/ui/app_monitor.go
@@ -10,6 +10,7 @@ import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/data/binding"
+ "fyne.io/fyne/v2/driver/desktop"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
@@ -28,38 +29,39 @@ type appMonitor struct {
monitorData *model.PushModelList
}
-func (this *appMonitor) LazyInit(service service.PttService, obs observer.Observer) error {
- this.obs = obs
- this.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_MONITOR, theme.MediaVideoIcon(), nil)
+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
- this.logPanel = widget.NewMultiLineEntry()
- this.logPanel.Wrapping = fyne.TextWrapWord
+ app.logPanel = widget.NewMultiLineEntry()
+ app.logPanel.Wrapping = fyne.TextWrapWord
//clear button
clearBtn := widget.NewButtonWithIcon(common.APP_TESTCASE_BTN_CLEARLOG, theme.DeleteIcon(), func() {
- this.logPanel.SetText("")
- this.monitorBinding.Set([]interface{}{})
+ app.logPanel.SetText("")
+ app.monitorBinding.Set([]interface{}{})
})
- resPanel := container.NewBorder(container.NewHBox(clearBtn, layout.NewSpacer()), nil, nil, nil, this.logPanel)
+ resPanel := container.NewBorder(container.NewHBox(clearBtn, layout.NewSpacer()), nil, nil, nil, app.logPanel)
- this.monitorBinding = binding.NewUntypedList()
- this.monitorData = model.NewPushModelList()
- this.createMonitorList()
+ app.monitorBinding = binding.NewUntypedList()
+ app.monitorData = model.NewPushModelList()
+ app.createMonitorList()
// layout
- panel := container.NewVSplit(container.NewBorder(this.monitorHeader, nil, nil, nil, this.monitorList), resPanel)
+ panel := container.NewVSplit(container.NewBorder(app.monitorHeader, nil, nil, nil, app.monitorList), resPanel)
+ panel.Offset = 0.8
content.Objects = append(content.Objects, panel)
- this.tabItem.Content = content
- this.Run()
+ app.tabItem.Content = content
+ app.Run()
return nil
}
-func (a *appMonitor) OpenDefault() bool {
- return true
+func (a *appMonitor) OpenDefault() string {
+ return common.TOOLBAR_MONITOR
}
func (a *appMonitor) GetAppName() string {
@@ -71,12 +73,12 @@ func (a appMonitor) OnClose() bool {
}
// monitor list data
-func (this *appMonitor) Run() {
- this.obs.AddListener(observer.EVENT_APP_MONI, observer.Listener{
+func (app *appMonitor) Run() {
+ app.obs.AddListener(observer.EVENT_APP_MONI, observer.Listener{
OnNotify: func(d interface{}, args ...interface{}) {
data := d.(*model.PushModel)
- this.monitorData.DataList = append(this.monitorData.DataList, data)
- this.reloadMonitorData()
+ app.monitorData.DataList = append(app.monitorData.DataList, data)
+ app.reloadMonitorData()
common.ShowCanvasTip("收到新的数据推送,请打开[推送]页面")
},
})
@@ -142,3 +144,11 @@ func (this *appMonitor) createMonitorList() {
}
}
+
+func (this *appMonitor) ShortCut() fyne.Shortcut {
+ return &desktop.CustomShortcut{KeyName: fyne.Key3, Modifier: desktop.AltModifier}
+}
+
+func (this *appMonitor) Icon() fyne.Resource {
+ return theme.MediaVideoIcon()
+}
diff --git a/cmd/v2/ui/app_test.go b/cmd/v2/ui/app_test.go
new file mode 100644
index 000000000..447c3bff0
--- /dev/null
+++ b/cmd/v2/ui/app_test.go
@@ -0,0 +1,18 @@
+package ui
+
+import (
+ "fmt"
+ cfg "go_dreamfactory/cmd/v2/configure/structs"
+ "go_dreamfactory/cmd/v2/lib/common"
+ "testing"
+)
+
+func TestGjson(t *testing.T) {
+ if tables, err := cfg.NewTables(common.Loader); err != nil {
+ println(err.Error())
+ } else {
+ for _, v := range tables.TestFlow.GetDataList() {
+ fmt.Println(v.Msg)
+ }
+ }
+}
diff --git a/cmd/v2/ui/app_testcase.go b/cmd/v2/ui/app_testcase.go
index ccf722f8c..fa43eed70 100644
--- a/cmd/v2/ui/app_testcase.go
+++ b/cmd/v2/ui/app_testcase.go
@@ -11,6 +11,7 @@ import (
"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"
@@ -41,7 +42,7 @@ func (a *appTester) LazyInit(service service.PttService, obs observer.Observer)
intro := widget.NewLabel("")
intro.Wrapping = fyne.TextWrapWord
caseContent := container.NewBorder(
- container.NewVBox(title, widget.NewSeparator(), intro), nil, nil, nil, content)
+ container.NewVBox(container.NewHBox(title, widget.NewSeparator(), widget.NewButton("压测", nil)), widget.NewSeparator(), intro), nil, nil, nil, content)
setNav := func(t *model.TestCase) {
defer a.progress.Hide()
@@ -170,3 +171,15 @@ func (a *appTester) makeNav(setNav func(testCase *model.TestCase)) fyne.CanvasOb
}
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
+}
diff --git a/cmd/v2/ui/main_menu.go b/cmd/v2/ui/main_menu.go
index 96316d982..8fb148aa4 100644
--- a/cmd/v2/ui/main_menu.go
+++ b/cmd/v2/ui/main_menu.go
@@ -2,30 +2,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
- helpMenu *fyne.Menu
- sysLog *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
+func newMainMenu() *mainMenu {
+ var mm mainMenu
-// // help
-// mm.sysLog = fyne.NewMenuItem("Show Log", func() {
-// newLogViewer().Win.Show()
-// })
-// mm.helpMenu = fyne.NewMenu("Help",
-// mm.sysLog,
-// // mm.aboutSelf,
-// )
+ // 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].Shortcut = app.ShortCut()
+ mm.appMenus[i].Icon = app.Icon()
+ }
-// mm.MainMenu = fyne.NewMainMenu(
-// mm.helpMenu,
-// )
-// return &mm
-// }
+ 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
+}
diff --git a/cmd/v2/ui/mainwindow.go b/cmd/v2/ui/mainwindow.go
index 18fdda765..deb88b42d 100644
--- a/cmd/v2/ui/mainwindow.go
+++ b/cmd/v2/ui/mainwindow.go
@@ -7,6 +7,7 @@ import (
"go_dreamfactory/cmd/v2/service"
"go_dreamfactory/cmd/v2/service/observer"
"go_dreamfactory/comm"
+ "go_dreamfactory/lego/sys/log"
"go_dreamfactory/modules/user"
"go_dreamfactory/pb"
"strings"
@@ -20,11 +21,11 @@ import (
"github.com/Pallinder/go-randomdata"
"github.com/sirupsen/logrus"
"github.com/spf13/cast"
+ "golang.design/x/hotkey"
)
var (
globalWin *MainWindowImpl
- toolWin *ToolWindowImpl
)
type MainWindow interface {
@@ -34,12 +35,13 @@ type MainWindow interface {
type MainWindowImpl struct {
UIImpl
WindowDefaultOptions
- parent fyne.Window
- w fyne.Window
- tb *toolBar //工具条
- toys *toys // side
- sb *statusBar //状态栏
- at *appContainer //tabs
+ 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 {
@@ -81,27 +83,35 @@ func (ui *MainWindowImpl) createWindowContainer() {
// tool bar
toolbar := widget.NewToolbar(
widget.NewToolbarAction(theme.MediaVideoIcon(), func() {
- openApp2(common.TOOLBAR_MONITOR)
+ openApp(ui.at, common.TOOLBAR_MONITOR)
}),
widget.NewToolbarAction(theme.DocumentIcon(), func() {
- openApp2(common.TOOLBAR_TESTER)
+ 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()
- }),
+ // 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)
+ ui.registerShortCut()
}
func (ui *MainWindowImpl) SetStatusMsg(msg string) {
@@ -115,7 +125,35 @@ func (ui *MainWindowImpl) quiteHandle() {
}
ui.app.Quit()
}, ui.w)
+}
+func (ui *MainWindowImpl) registerShortCut() {
+ for _, myApp := range appRegister {
+ ap := myApp
+ sc := ap.ShortCut()
+ ui.w.Canvas().AddShortcut(sc, func(_ fyne.Shortcut) {
+ err := globalWin.at.openApp(ap)
+ if err != nil {
+ log.Errorf("open app %v err:%v", ap.GetAppName(), err)
+ }
+ })
+ }
+
+ go func() {
+ hk := hotkey.New([]hotkey.Modifier{hotkey.ModCtrl, hotkey.ModShift}, hotkey.KeyZ)
+ if err := hk.Register(); err != nil {
+ log.Errorf("%v", err)
+ return
+ }
+ defer hk.Unregister()
+ for range hk.Keydown() {
+ // if globalWin.wStat.shown {
+ // globalWin.hideWin()
+ // } else {
+ // globalWin.showWin()
+ // }
+ }
+ }()
}
// CreateWindow ....
@@ -169,6 +207,7 @@ func (ui *MainWindowImpl) createChooseServerPopUp(w fyne.Window) error {
func (ui *MainWindowImpl) createChooseServerWindow(
title string,
ch chan string) fyne.Window {
+ w := fyne.CurrentApp().NewWindow(title)
// choose server button func
makeButton := func(s *service.ServiceConf, parent fyne.Window) *widget.Button {
btn := widget.NewButton(s.Name, func() {
@@ -183,11 +222,12 @@ func (ui *MainWindowImpl) createChooseServerWindow(
dialog.ShowError(err, parent)
} else {
ch <- fmt.Sprintf("%s:%s", s.SId, s.Name)
+ w.Close()
}
})
return btn
}
- w := fyne.CurrentApp().NewWindow(title)
+
sGrid := container.NewGridWithColumns(2)
config := ui.configService.GetConfig()
if config != nil {
@@ -225,7 +265,7 @@ func (ui *MainWindowImpl) createLoginWin(sid, sname string) {
if account.Text != "" {
logrus.WithField("account", account.Text).Debug("submit login")
ui.createWindowContainer()
- appName, err := ui.at.openDefaultApp()
+ appName, err := ui.at.openDefaultApp(common.TOOLBAR_MONITOR)
if err != nil {
logrus.WithField("appName", appName).Error(err)
}
diff --git a/cmd/v2/ui/perf_conf.go b/cmd/v2/ui/perf_conf.go
new file mode 100644
index 000000000..b7cb52fa2
--- /dev/null
+++ b/cmd/v2/ui/perf_conf.go
@@ -0,0 +1,114 @@
+package ui
+
+import (
+ "go_dreamfactory/cmd/v2/lib"
+ "go_dreamfactory/cmd/v2/lib/common"
+ "go_dreamfactory/cmd/v2/lib/storage"
+ "go_dreamfactory/cmd/v2/service"
+ "go_dreamfactory/cmd/v2/service/observer"
+ "time"
+
+ "fyne.io/fyne/v2"
+ "fyne.io/fyne/v2/container"
+ "fyne.io/fyne/v2/theme"
+ "fyne.io/fyne/v2/widget"
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/cast"
+)
+
+type perfConf struct {
+ appAdapter
+
+ obs observer.Observer
+ conf *storage.Config
+}
+
+func (app *perfConf) LazyInit(ptService service.PttService, obs observer.Observer) error {
+ app.obs = obs
+ app.conf = perfWin.UIImpl.config
+
+ app.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_PERF_CONF, theme.ContentCopyIcon(), nil)
+ content := container.NewMax()
+ content.Objects = []fyne.CanvasObject{}
+
+ // 压测form
+ wsAddrEntry := widget.NewEntry()
+ wsAddrEntry.PlaceHolder = "服务地址"
+ wsAddrEntry.Text = app.conf.WsAddr
+
+ timeoutEntry := widget.NewEntry()
+ timeoutEntry.PlaceHolder = "毫秒数"
+ timeoutEntry.Text = cast.ToString(app.conf.Pressure.TimeoutMs)
+
+ lpsEntry := widget.NewEntry()
+ lpsEntry.PlaceHolder = "并发数量"
+ lpsEntry.Text = cast.ToString(app.conf.Pressure.Concurrency)
+
+ durationEntry := widget.NewEntry()
+ durationEntry.PlaceHolder = "秒数"
+ durationEntry.Text = cast.ToString(app.conf.Pressure.DurationS)
+
+ userCountEntry := widget.NewEntry()
+ userCountEntry.PlaceHolder = "自动创建的用户数"
+ userCountEntry.Text = cast.ToString(app.conf.UserCount)
+
+ form := widget.NewForm(
+ widget.NewFormItem("超时(ms)", timeoutEntry),
+ widget.NewFormItem("并发量", lpsEntry),
+ widget.NewFormItem("持续时间(s)", durationEntry),
+ widget.NewFormItem("用户数", userCountEntry),
+ )
+ form.OnSubmit = func() {
+ pressure := app.conf.Pressure
+ pressure.TimeoutMs = cast.ToInt32(timeoutEntry.Text)
+ pressure.Concurrency = cast.ToInt32(lpsEntry.Text)
+ pressure.DurationS = cast.ToInt32(durationEntry.Text)
+ app.conf.Pressure = pressure
+ app.conf.UserCount = cast.ToInt32(userCountEntry.Text)
+ app.conf.WsAddr = wsAddrEntry.Text
+ if err := perfWin.UIImpl.storage.StoreConfig(app.conf); err != nil {
+ logrus.Error(err)
+ }
+
+ // new assistant
+ app.createAssistant()
+
+ //next
+ openApp(perfWin.tabs, common.TOOLBAR_PERF_PB)
+ }
+ form.SubmitText = "下一步"
+ form.OnCancel = func() {
+ timeoutEntry.Text = ""
+ lpsEntry.Text = ""
+ durationEntry.Text = ""
+ userCountEntry.Text = ""
+ wsAddrEntry.Text = ""
+ form.Refresh()
+ }
+ form.CancelText = "重置"
+
+ content.Objects = append(content.Objects, form)
+ app.tabItem.Content = content
+ return nil
+}
+
+func (a *perfConf) GetAppName() string {
+ return common.TOOLBAR_PERF_CONF
+}
+
+func (a *perfConf) createAssistant() {
+ param := lib.ParamMgr{
+ Caller: service.NewWsCli(a.conf.WsAddr),
+ Timeout: time.Duration(a.conf.Pressure.TimeoutMs) * time.Second,
+ Lps: uint32(a.conf.Pressure.Concurrency),
+ Duration: time.Duration(a.conf.Pressure.DurationS) * time.Second,
+ ResultCh: make(chan *lib.CallResult, 50),
+ }
+ assist, err := lib.NewAssistant(param)
+ if err != nil {
+ logrus.Errorf("AI助手初始化错误: %v", err)
+ return
+ }
+ logrus.WithField("assistant", assist).Info("AI助手")
+ perfWin.assistant = assist
+}
diff --git a/cmd/v2/ui/perf_pb.go b/cmd/v2/ui/perf_pb.go
new file mode 100644
index 000000000..f6a1588f7
--- /dev/null
+++ b/cmd/v2/ui/perf_pb.go
@@ -0,0 +1,91 @@
+package ui
+
+import (
+ "fmt"
+ cfg "go_dreamfactory/cmd/v2/configure/structs"
+ "go_dreamfactory/cmd/v2/lib/common"
+ "go_dreamfactory/cmd/v2/lib/storage"
+ "go_dreamfactory/cmd/v2/service"
+ "go_dreamfactory/cmd/v2/service/observer"
+
+ "fyne.io/fyne/v2"
+ "fyne.io/fyne/v2/container"
+ "fyne.io/fyne/v2/layout"
+ "fyne.io/fyne/v2/theme"
+ "fyne.io/fyne/v2/widget"
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/cast"
+)
+
+type perfPb struct {
+ appAdapter
+
+ obs observer.Observer
+
+ itemList common.ItemList
+
+ pbList func() //协议列表
+ conf *storage.Config
+}
+
+func (app *perfPb) LazyInit(ptService service.PttService, obs observer.Observer) error {
+ app.obs = obs
+ app.conf = perfWin.UIImpl.config
+
+ app.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_PERF_PB, theme.ContentCopyIcon(), nil)
+ content := container.NewMax()
+ content.Objects = []fyne.CanvasObject{}
+
+ app.itemList = *common.NewItemList()
+ app.itemList.ItemList = app.itemList.CreateList()
+
+ app.pbList = func() {
+ if tables, err := cfg.NewTables(common.Loader); err != nil {
+ println(err.Error())
+ } else {
+ for _, v := range tables.TestFlow.GetDataList() {
+ item := common.Item{
+ Id: cast.ToString(v.Id),
+ Text: fmt.Sprintf("%-6d %-20s %-20s %s", v.Id, v.Msg, v.Route, v.Params),
+ Data: v,
+ }
+ app.itemList.AddItem(item)
+ }
+ }
+ }
+ defer app.pbList()
+
+ // 刷新按钮
+ refeshBtn := widget.NewButtonWithIcon("", theme.ViewRefreshIcon(), func() {
+ app.itemList.Reset()
+ app.pbList()
+ })
+
+ // next按钮
+ nextBtn := widget.NewButtonWithIcon("执行", theme.ConfirmIcon(), func() {
+ for _, item := range app.itemList.CachedList.Items {
+ if data, ok := item.Data.(*cfg.GameTestFlowData); ok {
+ logrus.Infof("%v %v", data.Route, data.Params)
+ }
+ }
+ })
+
+ //layout
+ c := container.NewBorder(container.NewHBox(refeshBtn), container.NewHBox(layout.NewSpacer(), nextBtn), nil, nil, app.itemList.ItemList)
+ content.Objects = append(content.Objects, c)
+ app.tabItem.Content = content
+ return nil
+}
+
+func (a *perfPb) GetAppName() string {
+ return common.TOOLBAR_PERF_PB
+}
+
+func (a *perfPb) run() {
+ if perfWin.assistant == nil {
+ return
+ }
+ perfWin.assistant.Start()
+
+ perfWin.assistant.ShowResult()
+}
diff --git a/cmd/v2/ui/perf_welcome.go b/cmd/v2/ui/perf_welcome.go
new file mode 100644
index 000000000..c0f4e2012
--- /dev/null
+++ b/cmd/v2/ui/perf_welcome.go
@@ -0,0 +1,58 @@
+package ui
+
+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/container"
+ "fyne.io/fyne/v2/theme"
+ "fyne.io/fyne/v2/widget"
+)
+
+type perfWelcome struct {
+ appAdapter
+
+ obs observer.Observer
+}
+
+func (app *perfWelcome) LazyInit(service service.PttService, obs observer.Observer) error {
+ app.obs = obs
+
+ app.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_PERF_TIP, theme.ContentCopyIcon(), nil)
+ content := container.NewMax()
+ content.Objects = []fyne.CanvasObject{}
+
+ wel := widget.NewRichTextFromMarkdown("# 自动化性能测试工具使用说明" +
+ `
+ * 基于Luban工具生成协议文件(json格式)
+ `)
+ for i := range wel.Segments {
+ if seg, ok := wel.Segments[i].(*widget.TextSegment); ok {
+ seg.Style.Alignment = fyne.TextAlignLeading
+ }
+ }
+
+ goBtn := widget.NewButton("开始测试 >>", func() {
+ openApp(perfWin.tabs, common.TOOLBAR_PERF_CONF)
+ })
+ app.tabItem.Content = container.NewCenter(
+ container.NewVBox(
+ wel,
+ goBtn,
+ ))
+ return nil
+}
+
+func (a *perfWelcome) OpenDefault() string {
+ return common.TOOLBAR_PERF_TIP
+}
+
+func (a *perfWelcome) GetAppName() string {
+ return common.TOOLBAR_PERF_TIP
+}
+
+func (a *perfWelcome) OnClose() bool {
+ return false
+}
diff --git a/cmd/v2/ui/perfwindow.go b/cmd/v2/ui/perfwindow.go
new file mode 100644
index 000000000..ed0b2be48
--- /dev/null
+++ b/cmd/v2/ui/perfwindow.go
@@ -0,0 +1,85 @@
+package ui
+
+import (
+ "fmt"
+ "go_dreamfactory/cmd/v2/lib"
+ "go_dreamfactory/cmd/v2/lib/common"
+
+ "fyne.io/fyne/v2"
+ "fyne.io/fyne/v2/container"
+ "fyne.io/fyne/v2/theme"
+ "fyne.io/fyne/v2/widget"
+ "github.com/sirupsen/logrus"
+)
+
+var perfWin *PerfWindowImpl
+
+type PerfWindow interface {
+ WindowInterface
+}
+
+type PerfWindowImpl struct {
+ UIImpl
+ parent fyne.Window
+ w fyne.Window
+ statusbar *statusBar //状态栏
+ tabs *appContainer //tabs
+ toolbar *toolBar //工具条
+ assistant lib.Aiassistant
+}
+
+func NewPerfWindow(ui *UIImpl, parent fyne.Window) PerfWindow {
+
+ pw := &PerfWindowImpl{
+ UIImpl: *ui,
+ parent: parent,
+ }
+
+ perfWin = pw
+ return pw
+}
+
+func (ui *PerfWindowImpl) GetWin() WindowInterface {
+ return perfWin
+}
+
+func (ui *PerfWindowImpl) CreateWindow(_ string, width, height float32, _ bool) {
+ 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
+
+ w.Resize(fyne.NewSize(width, height))
+ w.CenterOnScreen()
+ w.SetCloseIntercept(func() {
+ ui.parent.Show()
+ })
+
+ ui.statusbar = newStatusBar()
+ toolbar := widget.NewToolbar(
+ widget.NewToolbarAction(theme.MediaVideoIcon(), func() {
+ openApp(ui.tabs, common.TOOLBAR_PERF_TIP)
+ }),
+ widget.NewToolbarAction(theme.MediaVideoIcon(), func() {
+ openApp(ui.tabs, common.TOOLBAR_PERF_CONF)
+ }),
+ )
+ ui.toolbar = newToolBar(toolbar)
+
+ ui.tabs = newAppContainer(appRegister, ui.pttService, ui.obs)
+ content := container.NewBorder(ui.toolbar.toolbar, ui.statusbar.widget, nil, nil, ui.tabs)
+ ui.w.SetContent(content)
+
+ defer func() {
+ appName, err := ui.tabs.openDefaultApp(common.TOOLBAR_PERF_TIP)
+ if err != nil {
+ logrus.WithField("appName", appName).Error(err)
+ }
+ }()
+
+ w.SetCloseIntercept(func() {
+ ui.parent.Show()
+ w.Close()
+ })
+ w.Show()
+}
diff --git a/cmd/v2/ui/testconfig_win.go b/cmd/v2/ui/testconfig_win.go
new file mode 100644
index 000000000..c9098a322
--- /dev/null
+++ b/cmd/v2/ui/testconfig_win.go
@@ -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
+}
diff --git a/cmd/v2/ui/tool_bar.go b/cmd/v2/ui/tool_bar.go
index ff3041dfc..5506ab184 100644
--- a/cmd/v2/ui/tool_bar.go
+++ b/cmd/v2/ui/tool_bar.go
@@ -20,10 +20,10 @@ func newToolBar(items *widget.Toolbar) *toolBar {
}
// open app2
-func openApp2(name string) {
+func openApp(ac *appContainer, name string) {
for _, app := range appRegister {
if app.GetAppName() == name {
- err := globalWin.at.openApp(app)
+ err := ac.openApp(app)
if err != nil {
logrus.Error(fmt.Errorf("%s %v", app.GetAppName(), err))
}
@@ -31,13 +31,4 @@ func openApp2(name string) {
}
}
-func openApp1(name string) {
- for _, app := range toolRegister {
- if app.GetAppName() == name {
- err := toolWin.at.openApp(app)
- if err != nil {
- logrus.Error(fmt.Errorf("%s %v", app.GetAppName(), err))
- }
- }
- }
-}
+
diff --git a/cmd/v2/ui/tool_luban.go b/cmd/v2/ui/tool_luban.go
index 28f5e8f8f..a60a7952d 100644
--- a/cmd/v2/ui/tool_luban.go
+++ b/cmd/v2/ui/tool_luban.go
@@ -15,7 +15,7 @@ import (
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/layout"
- "fyne.io/fyne/v2/storage"
+ fyne_storage "fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
"github.com/sirupsen/logrus"
@@ -401,7 +401,7 @@ func openFolder(entry *widget.Entry, w fyne.Window) {
entry.Text = lu.Path()
entry.Refresh()
}, w)
- luri, _ := storage.ListerForURI(storage.NewFileURI("."))
+ luri, _ := fyne_storage.ListerForURI(fyne_storage.NewFileURI("."))
dConf.SetLocation(luri)
dConf.SetConfirmText("打开")
dConf.SetDismissText("取消")
@@ -419,7 +419,7 @@ func openFile(entry *widget.Entry, w fyne.Window) {
}, w)
dConf.SetConfirmText("打开")
dConf.SetDismissText("取消")
- dConf.SetFilter(storage.NewExtensionFileFilter([]string{".exe"}))
+ dConf.SetFilter(fyne_storage.NewExtensionFileFilter([]string{".exe"}))
dConf.Resize(fyne.NewSize(750, 500))
dConf.Show()
}
diff --git a/cmd/v2/ui/tool_pb.go b/cmd/v2/ui/tool_pb.go
index 9076b3379..f40443e01 100644
--- a/cmd/v2/ui/tool_pb.go
+++ b/cmd/v2/ui/tool_pb.go
@@ -17,7 +17,7 @@ import (
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/layout"
- "fyne.io/fyne/v2/storage"
+ fyne_storage "fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
"github.com/sirupsen/logrus"
@@ -47,7 +47,7 @@ func (this *appPbGen) LazyInit(ptService service.PttService, obs observer.Observ
entry.Text = lu.Path()
entry.Refresh()
}, toolWin.w)
- luri, _ := storage.ListerForURI(storage.NewFileURI("."))
+ luri, _ := fyne_storage.ListerForURI(fyne_storage.NewFileURI("."))
dConf.SetLocation(luri)
dConf.SetConfirmText("打开")
dConf.SetDismissText("取消")
diff --git a/cmd/v2/ui/tool_term.go b/cmd/v2/ui/tool_term.go
index 3a12d63d9..74bd4fbd3 100644
--- a/cmd/v2/ui/tool_term.go
+++ b/cmd/v2/ui/tool_term.go
@@ -40,19 +40,19 @@ type appTerm struct {
downloadList *common.ItemList //download列表
}
-func (this *appTerm) LazyInit(ptService service.PttService, obs observer.Observer) error {
- this.obs = obs
- this.sshService = &service.SSHService{}
- this.jsonList = common.NewItemList()
+func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer) error {
+ app.obs = obs
+ app.sshService = &service.SSHService{}
+ app.jsonList = common.NewItemList()
//progress
- this.cProgress = widget.NewProgressBarInfinite()
- this.cProgress.Hide()
+ app.cProgress = widget.NewProgressBarInfinite()
+ app.cProgress.Hide()
- this.upProgress = widget.NewProgressBar()
- this.upProgress.Hide()
+ app.upProgress = widget.NewProgressBar()
+ app.upProgress.Hide()
- this.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_TERM, theme.MailSendIcon(), nil)
+ app.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_TERM, theme.MailSendIcon(), nil)
content := container.NewMax()
content.Objects = []fyne.CanvasObject{}
@@ -198,8 +198,8 @@ func (this *appTerm) LazyInit(ptService service.PttService, obs observer.Observe
// 连接
connBtn.OnTapped = func() {
- this.cProgress.Show()
- this.cProgress.Start()
+ app.cProgress.Show()
+ app.cProgress.Start()
ciphers := []string{}
if ip.Text == "" {
@@ -230,21 +230,21 @@ func (this *appTerm) LazyInit(ptService service.PttService, obs observer.Observe
}
connBtn.Disable()
- err := this.sshService.Connect(userName.Text, password.Text, ip.Text, "", cast.ToInt(port.Text), ciphers)
+ err := app.sshService.Connect(userName.Text, password.Text, ip.Text, "", cast.ToInt(port.Text), ciphers)
if err != nil {
dialog.ShowError(err, toolWin.w)
- this.cProgress.Stop()
- this.cProgress.Hide()
+ app.cProgress.Stop()
+ app.cProgress.Hide()
connBtn.Enable()
return
} else {
- this.jsonList.LoadItem(localDir.Text)
+ app.jsonList.LoadItem(localDir.Text)
- this.cProgress.Stop()
- this.cProgress.Hide()
+ app.cProgress.Stop()
+ app.cProgress.Hide()
disConnBtn.Enable()
syncBtn.Enable()
- this.upProgress.Hide()
+ app.upProgress.Hide()
allCancelBtn.Show()
allSelBtn.Hide()
refreshBtn.Enable()
@@ -260,7 +260,7 @@ func (this *appTerm) LazyInit(ptService service.PttService, obs observer.Observe
allSelBtn.Hide()
allCancelBtn.Show()
}()
- this.jsonList.LoadItem(localDir.Text)
+ app.jsonList.LoadItem(localDir.Text)
}
refreshBtn.OnTapped = reloadItem
@@ -268,7 +268,7 @@ func (this *appTerm) LazyInit(ptService service.PttService, obs observer.Observe
disConnBtn.Disable()
disConnBtn.OnTapped = func() {
defer func() {
- this.jsonList.Reset()
+ app.jsonList.Reset()
connBtn.Enable()
disConnBtn.Disable()
syncBtn.Disable()
@@ -277,7 +277,7 @@ func (this *appTerm) LazyInit(ptService service.PttService, obs observer.Observe
refreshBtn.Disable()
dlBtn.Disable()
}()
- this.sshService.Close()
+ app.sshService.Close()
}
//资源管理器
@@ -348,42 +348,42 @@ func (this *appTerm) LazyInit(ptService service.PttService, obs observer.Observe
syncNext := func() {
defer func() {
syncBtn.Enable()
- this.upProgress.Hide()
+ app.upProgress.Hide()
reloadItem()
dialog.ShowInformation("提示", "所有文件均上传完毕,需等1-2分钟待文件热更", toolWin.w)
}()
syncBtn.Disable()
- this.upProgress.Show()
- this.upProgress.SetValue(0)
+ app.upProgress.Show()
+ app.upProgress.SetValue(0)
- len := len(this.jsonList.SelItemIds)
+ len := len(app.jsonList.SelItemIds)
num := 0.0
increment := func(wg *sync.WaitGroup) {
num += float64(1) / float64(len)
- this.upProgress.SetValue(num)
+ app.upProgress.SetValue(num)
wg.Done()
}
- for _, fileName := range this.jsonList.SelItemIds {
- this.endProgress.Add(1)
+ 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 := this.sshService.ScpCopy(filepath.Join(localDir.Text, fn), remoteDir.Text); err != nil {
+ 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(&this.endProgress)
+ increment(&app.endProgress)
// 移除已上传的
- this.jsonList.DeleteItem(fn)
+ app.jsonList.DeleteItem(fn)
common.ShowTip(fmt.Sprintf("%s 成功上传", fn))
}(fileName)
}
- this.endProgress.Wait()
- this.upProgress.SetValue(1)
+ app.endProgress.Wait()
+ app.upProgress.SetValue(1)
}
syncBtn.OnTapped = func() {
- if this.sshService.Client == nil {
+ if app.sshService.Client == nil {
dialog.ShowError(errors.New("请先连接终端"), toolWin.w)
return
}
@@ -395,7 +395,7 @@ func (this *appTerm) LazyInit(ptService service.PttService, obs observer.Observe
svnBtn.FocusGained()
return
} else {
- if len(this.jsonList.SelItemIds) == 0 {
+ if len(app.jsonList.SelItemIds) == 0 {
common.ShowTip("没有选择任何文件,或尝试点击【刷新】")
return
}
@@ -419,13 +419,13 @@ func (this *appTerm) LazyInit(ptService service.PttService, obs observer.Observe
// SVN更新
svnNext := func() {
defer func() {
- this.cProgress.Hide()
- this.cProgress.Stop()
+ app.cProgress.Hide()
+ app.cProgress.Stop()
svnBtn.Enable()
}()
svnBtn.Disable()
- this.cProgress.Show()
- this.cProgress.Start()
+ 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),
@@ -465,12 +465,12 @@ func (this *appTerm) LazyInit(ptService service.PttService, obs observer.Observe
allCancelBtn.Hide()
allSelBtn.Show()
}()
- for i, v := range this.jsonList.CachedList.Items {
- this.jsonList.CachedList.Items[i].Checked = true
- this.jsonList.SelItemIds = append(this.jsonList.SelItemIds, v.Text)
- this.jsonList.ItemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
+ 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))
}
- this.jsonList.ItemList.Refresh()
+ app.jsonList.ItemList.Refresh()
}
// 全选
@@ -479,18 +479,18 @@ func (this *appTerm) LazyInit(ptService service.PttService, obs observer.Observe
allCancelBtn.Show()
allSelBtn.Hide()
}()
- this.jsonList.SelItemIds = []string{}
- for i, v := range this.jsonList.CachedList.Items {
- this.jsonList.CachedList.Items[i].Checked = false
- this.jsonList.ItemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
+ 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))
}
- this.jsonList.ItemList.Refresh()
+ app.jsonList.ItemList.Refresh()
}
// 搜索
searchEntry.PlaceHolder = "搜索"
searchEntry.OnChanged = func(s string) {
- if this.sshService.Client == nil {
+ if app.sshService.Client == nil {
dialog.ShowError(errors.New("请先连接终端"), toolWin.w)
return
}
@@ -499,13 +499,13 @@ func (this *appTerm) LazyInit(ptService service.PttService, obs observer.Observe
} else {
// go func() {
newList := []common.Item{}
- for _, v := range this.jsonList.SearchItem {
+ for _, v := range app.jsonList.SearchItem {
if strings.Contains(v.Text, s) {
newList = append(newList, v)
}
}
- this.jsonList.CachedList.Items = newList
- this.jsonList.ItemList.Refresh()
+ app.jsonList.CachedList.Items = newList
+ app.jsonList.ItemList.Refresh()
// }()
}
}
@@ -513,7 +513,7 @@ func (this *appTerm) LazyInit(ptService service.PttService, obs observer.Observe
// 下载日志
dlBtn.Disable()
dlBtn.OnTapped = func() {
- w := this.createDownloadWindow()
+ w := app.createDownloadWindow()
w.Show()
w.SetCloseIntercept(func() {
dlBtn.Enable()
@@ -523,19 +523,19 @@ func (this *appTerm) LazyInit(ptService service.PttService, obs observer.Observe
}
// 创建json列表
- this.jsonList.ItemList = this.jsonList.CreateDefaultCheckList()
+ 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, this.cProgress), container.NewBorder(
+ btns1, svnForm, btns2, app.cProgress), container.NewBorder(
container.NewBorder(nil, nil, container.NewHBox(allCancelBtn, allSelBtn, syncBtn, refreshBtn), container.NewHBox(explorBtn), searchEntry),
- nil, nil, nil, this.jsonList.ItemList))
+ nil, nil, nil, app.jsonList.ItemList))
split.Offset = 0.45
- content.Objects = append(content.Objects, container.NewBorder(nil, this.upProgress, nil, nil, split))
+ content.Objects = append(content.Objects, container.NewBorder(nil, app.upProgress, nil, nil, split))
- this.tabItem.Content = content
+ app.tabItem.Content = content
return nil
}
diff --git a/cmd/v2/ui/tool_welcome.go b/cmd/v2/ui/tool_welcome.go
index e0dd8567e..2b466ea12 100644
--- a/cmd/v2/ui/tool_welcome.go
+++ b/cmd/v2/ui/tool_welcome.go
@@ -52,8 +52,8 @@ func (a *appWelcome) GetAppName() string {
return common.TOOLBAR_WEL
}
-func (a *appWelcome) OpenDefault() bool {
- return true
+func (a *appWelcome) OpenDefault() string {
+ return common.TOOLBAR_WEL
}
func (a *appWelcome) ShortCut() fyne.Shortcut {
diff --git a/cmd/v2/ui/toolwindow.go b/cmd/v2/ui/toolwindow.go
index e1598c410..db83edfd0 100644
--- a/cmd/v2/ui/toolwindow.go
+++ b/cmd/v2/ui/toolwindow.go
@@ -10,7 +10,7 @@ import (
"fyne.io/fyne/v2/widget"
"github.com/sirupsen/logrus"
)
-
+var toolWin *ToolWindowImpl
type ToolWindow interface {
WindowInterface
}
@@ -36,19 +36,19 @@ func NewToolWindow(ui *UIImpl, parent fyne.Window) ToolWindow {
toolbar := widget.NewToolbar(
widget.NewToolbarAction(theme.ContentCopyIcon(), func() {
- openApp1(common.TOOLBAR_GEN)
+ openApp(mw.at,common.TOOLBAR_GEN)
}),
widget.NewToolbarAction(theme.ContentAddIcon(), func() {
- openApp1(common.TOOLBAR_PB)
+ openApp(mw.at,common.TOOLBAR_PB)
}),
widget.NewToolbarAction(theme.DownloadIcon(), func() {
- openApp1(common.TOOLBAR_SEC)
+ openApp(mw.at,common.TOOLBAR_SEC)
}),
widget.NewToolbarAction(theme.MailSendIcon(), func() {
- openApp1(common.TOOLBAR_TERM)
+ openApp(mw.at,common.TOOLBAR_TERM)
}),
widget.NewToolbarSpacer(),
@@ -59,11 +59,16 @@ func NewToolWindow(ui *UIImpl, parent fyne.Window) ToolWindow {
mw.tb = newToolBar(toolbar)
- mw.at = newAppContainer(toolRegister, nil, ui.obs)
+ mw.at = newAppContainer(appRegister, nil, ui.obs)
return mw
}
+func (ui *ToolWindowImpl) GetWin() WindowInterface {
+ return toolWin
+}
+
+
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)
@@ -73,7 +78,7 @@ func (ui *ToolWindowImpl) CreateWindow(title string, width, height float32, _ bo
content := container.NewBorder(ui.tb.toolbar, ui.sb.widget,
nil, nil, ui.at)
ui.w.SetContent(content)
- appName, err := ui.at.openDefaultApp()
+ appName, err := ui.at.openDefaultApp(common.TOOLBAR_WEL)
if err != nil {
logrus.WithField("appName", appName).Error(err)
}
diff --git a/cmd/v2/ui/ui.go b/cmd/v2/ui/ui.go
index 38e00ed11..57ef7a3eb 100644
--- a/cmd/v2/ui/ui.go
+++ b/cmd/v2/ui/ui.go
@@ -1,6 +1,7 @@
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"
@@ -9,6 +10,7 @@ import (
"fyne.io/fyne/v2"
"github.com/BabySid/gobase"
+ "github.com/sirupsen/logrus"
)
var uid string
@@ -27,6 +29,8 @@ type UIImpl struct {
pttService service.PttService
configService service.ConfigService
obs observer.Observer
+ storage storage.Storage
+ config *storage.Config
}
func NewUI(app fyne.App,
@@ -34,8 +38,21 @@ func NewUI(app fyne.App,
connService service.ConnService,
pttService service.PttService,
obs observer.Observer,
-) *UIImpl {
+) (*UIImpl, error) {
app.Settings().SetTheme(&theme.MyTheme{})
+
+ storage, err := storage.NewOSStorage()
+ if err != nil {
+ logrus.Errorf("new storage err:%v", err)
+ return nil, err
+ }
+
+ // 加载配置
+ config, err := storage.LoadConfig()
+ if err != nil {
+ logrus.Errorf("Load config err:%v", err)
+ return nil, err
+ }
return &UIImpl{
app: app,
windows: make(map[string]fyne.Window),
@@ -44,7 +61,9 @@ func NewUI(app fyne.App,
connService: connService,
pttService: pttService,
obs: obs,
- }
+ storage: storage,
+ config: config,
+ }, nil
}
func (ui *UIImpl) AddWindow(name string, w fyne.Window) {
diff --git a/cmd/v2/ui/views/baseformview.go b/cmd/v2/ui/views/baseformview.go
index 1f3479b2f..914653343 100644
--- a/cmd/v2/ui/views/baseformview.go
+++ b/cmd/v2/ui/views/baseformview.go
@@ -17,15 +17,15 @@ type BaseformView struct {
service service.PttService
}
-func (this *BaseformView) Init(service service.PttService, obs observer.Observer, w fyne.Window, res *widget.Entry) {
- this.service = service
- this.obs = obs
- this.w = w
- this.res = res
- this.form = widget.NewForm()
- this.form.SubmitText = common.BUTTON_OK
+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 (this *BaseformView) Load() {
- this.form.OnSubmit()
+func (view *BaseformView) Load() {
+ view.form.OnSubmit()
}
diff --git a/cmd/v2/ui/views/sociaty_create.go b/cmd/v2/ui/views/sociaty_create.go
index 40a453a90..3302c19b6 100644
--- a/cmd/v2/ui/views/sociaty_create.go
+++ b/cmd/v2/ui/views/sociaty_create.go
@@ -17,7 +17,7 @@ type SociatyCreateView struct {
BaseformView
}
-func (this *SociatyCreateView) CreateView(t *model.TestCase) fyne.CanvasObject {
+func (app *SociatyCreateView) CreateView(t *model.TestCase) fyne.CanvasObject {
sociatyName := widget.NewEntry()
notice := widget.NewMultiLineEntry()
icon := widget.NewEntry()
@@ -26,26 +26,29 @@ func (this *SociatyCreateView) CreateView(t *model.TestCase) fyne.CanvasObject {
applyLv := widget.NewEntry()
applyLv.Text = "1" //默认
- this.form.AppendItem(widget.NewFormItem("公会名称", sociatyName))
- this.form.AppendItem(widget.NewFormItem("公告", notice))
- this.form.AppendItem(widget.NewFormItem("图标", icon))
- this.form.AppendItem(widget.NewFormItem("审批", isApplyCheck))
- this.form.AppendItem(widget.NewFormItem("入会等级", applyLv))
+ app.form.AppendItem(widget.NewFormItem("公会名称", sociatyName))
+ app.form.AppendItem(widget.NewFormItem("公告", notice))
+ app.form.AppendItem(widget.NewFormItem("图标", icon))
+ app.form.AppendItem(widget.NewFormItem("审批", isApplyCheck))
+ app.form.AppendItem(widget.NewFormItem("入会等级", applyLv))
- this.form.OnSubmit = func() {
+ app.form.OnSubmit = func() {
+ req := &pb.SociatyCreateReq{
+ Name: sociatyName.Text,
+ Icon: icon.Text,
+ Notice: notice.Text,
+ IsApplyCheck: isApplyCheck.Checked,
+ ApplyLv: cast.ToInt32(applyLv.Text),
+ }
if err := service.GetPttService().SendToClient(
string(comm.ModuleSociaty),
sociaty.SociatySubTypeCreate,
- &pb.SociatyCreateReq{
- Name: sociatyName.Text,
- Icon: icon.Text,
- Notice: notice.Text,
- IsApplyCheck: isApplyCheck.Checked,
- ApplyLv: cast.ToInt32(applyLv.Text),
- }); err != nil {
+ req,
+ ); err != nil {
logrus.Error(err)
}
+ logrus.WithFields(logrus.Fields{"mainType": string(comm.ModuleSociaty), "subType": sociaty.SociatySubTypeCreate, "params": req}).Info("创建工会")
}
- this.form.SubmitText = "创建"
- return this.form
+ app.form.SubmitText = "创建"
+ return app.form
}
diff --git a/cmd/v2/ui/views/sys_funclist.go b/cmd/v2/ui/views/sys_funclist.go
index a147fa628..5365ff1e1 100644
--- a/cmd/v2/ui/views/sys_funclist.go
+++ b/cmd/v2/ui/views/sys_funclist.go
@@ -15,14 +15,16 @@ type SysFuncListView struct {
func (this *SysFuncListView) CreateView(t *model.TestCase) fyne.CanvasObject {
this.form.OnSubmit = func() {
+ req := &pb.SysFuncListReq{}
if err := service.GetPttService().SendToClient(
t.MainType,
t.SubType,
- &pb.SysFuncListReq{},
+ req,
); err != nil {
logrus.Error(err)
return
}
+ logrus.WithFields(logrus.Fields{"mainType": t.MainType, "subType": t.SubType, "params": req}).Info("功能开启列表")
}
return this.form
}
diff --git a/go.mod b/go.mod
index 2461bd9c8..ce90ee710 100644
--- a/go.mod
+++ b/go.mod
@@ -178,6 +178,7 @@ require (
go.opentelemetry.io/otel/trace v1.6.3 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/zap v1.17.0 // indirect
+ golang.design/x/hotkey v0.4.0
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd // indirect
golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee // indirect
diff --git a/go.sum b/go.sum
index 77b371f61..c40139098 100644
--- a/go.sum
+++ b/go.sum
@@ -845,6 +845,8 @@ go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
+golang.design/x/hotkey v0.4.0 h1:jmY6QJdakEdYn0KBm48IZRw3emBpDXRhIWUHqPVsWBY=
+golang.design/x/hotkey v0.4.0/go.mod h1:M8SGcwFYHnKRa83FpTFQoZvPO5vVT+kWPztFqTQKmXA=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=