parent
ec75fee2b1
commit
5b95e1b051
@ -1,42 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
// <auto-generated>
|
|
||||||
// This code was generated by a tool.
|
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
// the code is regenerated.
|
|
||||||
// </auto-generated>
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
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]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
// <auto-generated>
|
|
||||||
// This code was generated by a tool.
|
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
// the code is regenerated.
|
|
||||||
// </auto-generated>
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
// <auto-generated>
|
|
||||||
// This code was generated by a tool.
|
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
// the code is regenerated.
|
|
||||||
// </auto-generated>
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"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": ""
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,255 +0,0 @@
|
|||||||
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("读取结果")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
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
|
|
||||||
)
|
|
@ -6,12 +6,6 @@ type (
|
|||||||
WindowAction int64
|
WindowAction int64
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
MainType = "mainType"
|
|
||||||
SubType = "subType"
|
|
||||||
Params = "params"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
WindowAspect_Normal WindowAspect = iota
|
WindowAspect_Normal WindowAspect = iota
|
||||||
WindowAspect_FullScreen
|
WindowAspect_FullScreen
|
||||||
|
@ -71,7 +71,6 @@ package common
|
|||||||
// zh
|
// zh
|
||||||
const (
|
const (
|
||||||
APP_NAME = "机器人"
|
APP_NAME = "机器人"
|
||||||
|
|
||||||
// app 子标题 [0.0.1 build-1] 应用名称
|
// app 子标题 [0.0.1 build-1] 应用名称
|
||||||
APP_WIN_TITLE = "%s [%s build-%d] %s"
|
APP_WIN_TITLE = "%s [%s build-%d] %s"
|
||||||
WELCOME_MSG = "欢迎使用工具箱"
|
WELCOME_MSG = "欢迎使用工具箱"
|
||||||
@ -95,11 +94,6 @@ const (
|
|||||||
TOOLBAR_WEL = "欢迎"
|
TOOLBAR_WEL = "欢迎"
|
||||||
TOOLBAR_TERM = "同步配置"
|
TOOLBAR_TERM = "同步配置"
|
||||||
TOOLBAR_PB = "protobuf"
|
TOOLBAR_PB = "protobuf"
|
||||||
TOOLBAR_AUTO = "自动化"
|
|
||||||
|
|
||||||
TOOLBAR_PERF_TIP = "使用说明"
|
|
||||||
TOOLBAR_PERF_CONF = "配置"
|
|
||||||
TOOLBAR_PERF_PB = "协议"
|
|
||||||
|
|
||||||
//monitor
|
//monitor
|
||||||
APP_MONITOR_TITLE_ID = "编号"
|
APP_MONITOR_TITLE_ID = "编号"
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
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"`
|
|
||||||
}
|
|
@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -157,15 +156,3 @@ func ConvertFileSize(size int64) string {
|
|||||||
|
|
||||||
return "0"
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
package lib
|
|
||||||
|
|
||||||
type Aiassistant interface {
|
|
||||||
Start() bool
|
|
||||||
Stop() error
|
|
||||||
ShowResult()
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
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))
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
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"` //持续时间 秒
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
@ -1,117 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -8,7 +8,6 @@ import (
|
|||||||
"go_dreamfactory/cmd/v2/service/observer"
|
"go_dreamfactory/cmd/v2/service/observer"
|
||||||
"go_dreamfactory/cmd/v2/theme"
|
"go_dreamfactory/cmd/v2/theme"
|
||||||
"go_dreamfactory/cmd/v2/ui"
|
"go_dreamfactory/cmd/v2/ui"
|
||||||
"image/color"
|
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@ -18,7 +17,6 @@ import (
|
|||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/app"
|
"fyne.io/fyne/v2/app"
|
||||||
"fyne.io/fyne/v2/canvas"
|
|
||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
"fyne.io/fyne/v2/dialog"
|
"fyne.io/fyne/v2/dialog"
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
@ -69,13 +67,7 @@ func main() {
|
|||||||
// create a new ui
|
// create a new ui
|
||||||
app := app.NewWithID("df-toolkit")
|
app := app.NewWithID("df-toolkit")
|
||||||
app.SetIcon(theme.ResourceAppPng)
|
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)
|
// logLifecycle(app)
|
||||||
|
|
||||||
//创建enter
|
//创建enter
|
||||||
@ -86,7 +78,7 @@ func main() {
|
|||||||
checkVersion(app, w)
|
checkVersion(app, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
w.SetContent(container.NewGridWithColumns(3,
|
w.SetContent(container.NewGridWithColumns(2,
|
||||||
widget.NewButton("工具", func() {
|
widget.NewButton("工具", func() {
|
||||||
toolWindow := ui.NewToolWindow(appUI, w)
|
toolWindow := ui.NewToolWindow(appUI, w)
|
||||||
toolWindow.CreateWindow(common.APP_NAME, 1499, 800, true)
|
toolWindow.CreateWindow(common.APP_NAME, 1499, 800, true)
|
||||||
@ -96,13 +88,7 @@ func main() {
|
|||||||
mainWindow := ui.NewMainWindow(appUI, w)
|
mainWindow := ui.NewMainWindow(appUI, w)
|
||||||
mainWindow.CreateWindow(common.APP_NAME, 1499, 800, true)
|
mainWindow.CreateWindow(common.APP_NAME, 1499, 800, true)
|
||||||
w.Hide()
|
w.Hide()
|
||||||
}),
|
})))
|
||||||
widget.NewButton("自动化测试", func() {
|
|
||||||
perfWindow := ui.NewPerfWindow(appUI, w)
|
|
||||||
perfWindow.CreateWindow(common.APP_NAME, 600, 800, true)
|
|
||||||
w.Hide()
|
|
||||||
}),
|
|
||||||
))
|
|
||||||
w.SetFixedSize(true)
|
w.SetFixedSize(true)
|
||||||
w.Resize(fyne.NewSize(400, 200))
|
w.Resize(fyne.NewSize(400, 200))
|
||||||
w.CenterOnScreen()
|
w.CenterOnScreen()
|
||||||
@ -110,7 +96,7 @@ func main() {
|
|||||||
app.Quit()
|
app.Quit()
|
||||||
})
|
})
|
||||||
|
|
||||||
logrus.WithField("version", app.Metadata().Version).Debug("app starting")
|
logrus.WithField("version", app.Metadata().Version).Info("app starting")
|
||||||
w.Show()
|
w.Show()
|
||||||
appUI.Run()
|
appUI.Run()
|
||||||
}
|
}
|
||||||
@ -158,13 +144,12 @@ func setupConfig() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setupLogger() (err error) {
|
func setupLogger() (err error) {
|
||||||
logrus.SetFormatter(&logrus.JSONFormatter{
|
logrus.SetFormatter(&logrus.TextFormatter{
|
||||||
TimestampFormat: "2006-01-02 15:04:05",
|
DisableColors: true,
|
||||||
// DisableColors: true,
|
FullTimestamp: true,
|
||||||
// FullTimestamp: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
logrus.SetLevel(logrus.InfoLevel)
|
logrus.SetLevel(logrus.DebugLevel)
|
||||||
logrus.SetOutput(os.Stdout)
|
logrus.SetOutput(os.Stdout)
|
||||||
|
|
||||||
//设置output,默认为stderr,可以为任何io.Writer,比如文件*os.File
|
//设置output,默认为stderr,可以为任何io.Writer,比如文件*os.File
|
||||||
|
@ -7,7 +7,7 @@ services:
|
|||||||
- service:
|
- service:
|
||||||
sid: "dfz"
|
sid: "dfz"
|
||||||
name: 赵长远
|
name: 赵长远
|
||||||
url: ws://10.0.5.145:7891/gateway
|
url: ws://10.0.0.238:7891/gateway
|
||||||
- service:
|
- service:
|
||||||
sid: "df01"
|
sid: "df01"
|
||||||
name: 内网
|
name: 内网
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
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()
|
|
||||||
}
|
|
@ -71,17 +71,14 @@ func (p *PttServiceImpl) SendToClient(mainType, subType string, rsp proto.Messag
|
|||||||
func (p *PttServiceImpl) Login(sid, account string) (code pb.ErrorCode) {
|
func (p *PttServiceImpl) Login(sid, account string) (code pb.ErrorCode) {
|
||||||
head := &pb.UserMessage{MainType: string(comm.ModuleUser), SubType: user.UserSubTypeLogin}
|
head := &pb.UserMessage{MainType: string(comm.ModuleUser), SubType: user.UserSubTypeLogin}
|
||||||
head.Sec = common.BuildSecStr(sid, account)
|
head.Sec = common.BuildSecStr(sid, account)
|
||||||
req := &pb.UserLoginReq{
|
if err := p.connService.SendMsg(head, &pb.UserLoginReq{
|
||||||
Account: account,
|
Account: account,
|
||||||
Sid: sid,
|
Sid: sid,
|
||||||
}
|
}); err != nil {
|
||||||
if err := p.connService.SendMsg(head, req); err != nil {
|
|
||||||
code = pb.ErrorCode_SystemError
|
code = pb.ErrorCode_SystemError
|
||||||
logrus.WithField("err", err).Error("Login")
|
logrus.WithField("err", err).Error("Login")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logrus.WithFields(logrus.Fields{common.MainType: string(comm.ModuleUser), common.SubType: user.UserSubTypeLogin,
|
|
||||||
common.Params: req}).Info("登录")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,160 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
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()
|
|
||||||
}
|
|
@ -61,10 +61,10 @@ func (at *appContainer) openApp(app appInterface) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// open default app
|
// open default app
|
||||||
func (at *appContainer) openDefaultApp(appName string) (string, error) {
|
func (at *appContainer) openDefaultApp() (string, error) {
|
||||||
var firstTab *container.TabItem
|
var firstTab *container.TabItem
|
||||||
for _, app := range at.ai {
|
for _, app := range at.ai {
|
||||||
if app.OpenDefault() == appName {
|
if app.OpenDefault() {
|
||||||
if err := at.initApp(app); err != nil {
|
if err := at.initApp(app); err != nil {
|
||||||
return app.GetAppName(), err
|
return app.GetAppName(), err
|
||||||
}
|
}
|
||||||
|
@ -4,47 +4,34 @@ import (
|
|||||||
"go_dreamfactory/cmd/v2/service"
|
"go_dreamfactory/cmd/v2/service"
|
||||||
"go_dreamfactory/cmd/v2/service/observer"
|
"go_dreamfactory/cmd/v2/service/observer"
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
|
||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
"fyne.io/fyne/v2/theme"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type appInterface interface {
|
type appInterface interface {
|
||||||
LazyInit(service service.PttService, obs observer.Observer) error
|
LazyInit(service service.PttService, obs observer.Observer) error
|
||||||
GetTabItem() *container.TabItem
|
GetTabItem() *container.TabItem
|
||||||
GetAppName() string
|
GetAppName() string
|
||||||
OpenDefault() string
|
OpenDefault() bool
|
||||||
GetUI() interface{}
|
|
||||||
OnClose() bool
|
OnClose() bool
|
||||||
ShortCut() fyne.Shortcut
|
|
||||||
Icon() fyne.Resource
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
appRegister = []appInterface{
|
appRegister = []appInterface{
|
||||||
&appMonitor{},
|
&appMonitor{},
|
||||||
&appTester{},
|
&appTester{},
|
||||||
&appAuto{},
|
}
|
||||||
|
|
||||||
|
toolRegister = []appInterface{
|
||||||
&appWelcome{},
|
&appWelcome{},
|
||||||
&appGen{},
|
&appGen{},
|
||||||
&appPbGen{},
|
&appPbGen{},
|
||||||
&appLock{},
|
&appLock{},
|
||||||
&appTerm{},
|
&appTerm{},
|
||||||
|
|
||||||
&perfWelcome{},
|
|
||||||
&perfConf{},
|
|
||||||
&perfPb{},
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
type appAdapter struct {
|
type appAdapter struct {
|
||||||
tabItem *container.TabItem
|
tabItem *container.TabItem
|
||||||
ai []appInterface
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a appAdapter) ShortCut() fyne.Shortcut {
|
|
||||||
panic("implement Shortcut")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a appAdapter) LazyInit() error {
|
func (a appAdapter) LazyInit() error {
|
||||||
@ -55,12 +42,8 @@ func (a appAdapter) GetAppName() string {
|
|||||||
panic("implement GetAppName()")
|
panic("implement GetAppName()")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a appAdapter) GetUI() interface{} {
|
func (a appAdapter) OpenDefault() bool {
|
||||||
panic("implement GetUI()")
|
return false
|
||||||
}
|
|
||||||
|
|
||||||
func (a appAdapter) OpenDefault() string {
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a appAdapter) GetTabItem() *container.TabItem {
|
func (a appAdapter) GetTabItem() *container.TabItem {
|
||||||
@ -70,7 +53,3 @@ func (a appAdapter) GetTabItem() *container.TabItem {
|
|||||||
func (a appAdapter) OnClose() bool {
|
func (a appAdapter) OnClose() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a appAdapter) Icon() fyne.Resource {
|
|
||||||
return theme.FyneLogo()
|
|
||||||
}
|
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
"fyne.io/fyne/v2/data/binding"
|
"fyne.io/fyne/v2/data/binding"
|
||||||
"fyne.io/fyne/v2/driver/desktop"
|
|
||||||
"fyne.io/fyne/v2/layout"
|
"fyne.io/fyne/v2/layout"
|
||||||
"fyne.io/fyne/v2/theme"
|
"fyne.io/fyne/v2/theme"
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
@ -29,39 +28,38 @@ type appMonitor struct {
|
|||||||
monitorData *model.PushModelList
|
monitorData *model.PushModelList
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *appMonitor) LazyInit(service service.PttService, obs observer.Observer) error {
|
func (this *appMonitor) LazyInit(service service.PttService, obs observer.Observer) error {
|
||||||
app.obs = obs
|
this.obs = obs
|
||||||
app.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_MONITOR, theme.MediaVideoIcon(), nil)
|
this.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_MONITOR, theme.MediaVideoIcon(), nil)
|
||||||
|
|
||||||
content := container.NewMax()
|
content := container.NewMax()
|
||||||
content.Objects = []fyne.CanvasObject{}
|
content.Objects = []fyne.CanvasObject{}
|
||||||
|
|
||||||
// panel for output log
|
// panel for output log
|
||||||
app.logPanel = widget.NewMultiLineEntry()
|
this.logPanel = widget.NewMultiLineEntry()
|
||||||
app.logPanel.Wrapping = fyne.TextWrapWord
|
this.logPanel.Wrapping = fyne.TextWrapWord
|
||||||
//clear button
|
//clear button
|
||||||
clearBtn := widget.NewButtonWithIcon(common.APP_TESTCASE_BTN_CLEARLOG, theme.DeleteIcon(), func() {
|
clearBtn := widget.NewButtonWithIcon(common.APP_TESTCASE_BTN_CLEARLOG, theme.DeleteIcon(), func() {
|
||||||
app.logPanel.SetText("")
|
this.logPanel.SetText("")
|
||||||
app.monitorBinding.Set([]interface{}{})
|
this.monitorBinding.Set([]interface{}{})
|
||||||
})
|
})
|
||||||
|
|
||||||
resPanel := container.NewBorder(container.NewHBox(clearBtn, layout.NewSpacer()), nil, nil, nil, app.logPanel)
|
resPanel := container.NewBorder(container.NewHBox(clearBtn, layout.NewSpacer()), nil, nil, nil, this.logPanel)
|
||||||
|
|
||||||
app.monitorBinding = binding.NewUntypedList()
|
this.monitorBinding = binding.NewUntypedList()
|
||||||
app.monitorData = model.NewPushModelList()
|
this.monitorData = model.NewPushModelList()
|
||||||
app.createMonitorList()
|
this.createMonitorList()
|
||||||
|
|
||||||
// layout
|
// layout
|
||||||
panel := container.NewVSplit(container.NewBorder(app.monitorHeader, nil, nil, nil, app.monitorList), resPanel)
|
panel := container.NewVSplit(container.NewBorder(this.monitorHeader, nil, nil, nil, this.monitorList), resPanel)
|
||||||
panel.Offset = 0.8
|
|
||||||
content.Objects = append(content.Objects, panel)
|
content.Objects = append(content.Objects, panel)
|
||||||
app.tabItem.Content = content
|
this.tabItem.Content = content
|
||||||
app.Run()
|
this.Run()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appMonitor) OpenDefault() string {
|
func (a *appMonitor) OpenDefault() bool {
|
||||||
return common.TOOLBAR_MONITOR
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appMonitor) GetAppName() string {
|
func (a *appMonitor) GetAppName() string {
|
||||||
@ -73,12 +71,12 @@ func (a appMonitor) OnClose() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// monitor list data
|
// monitor list data
|
||||||
func (app *appMonitor) Run() {
|
func (this *appMonitor) Run() {
|
||||||
app.obs.AddListener(observer.EVENT_APP_MONI, observer.Listener{
|
this.obs.AddListener(observer.EVENT_APP_MONI, observer.Listener{
|
||||||
OnNotify: func(d interface{}, args ...interface{}) {
|
OnNotify: func(d interface{}, args ...interface{}) {
|
||||||
data := d.(*model.PushModel)
|
data := d.(*model.PushModel)
|
||||||
app.monitorData.DataList = append(app.monitorData.DataList, data)
|
this.monitorData.DataList = append(this.monitorData.DataList, data)
|
||||||
app.reloadMonitorData()
|
this.reloadMonitorData()
|
||||||
common.ShowCanvasTip("收到新的数据推送,请打开[推送]页面")
|
common.ShowCanvasTip("收到新的数据推送,请打开[推送]页面")
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -144,11 +142,3 @@ 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()
|
|
||||||
}
|
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,7 +11,6 @@ import (
|
|||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
"fyne.io/fyne/v2/driver/desktop"
|
|
||||||
"fyne.io/fyne/v2/layout"
|
"fyne.io/fyne/v2/layout"
|
||||||
"fyne.io/fyne/v2/theme"
|
"fyne.io/fyne/v2/theme"
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
@ -42,7 +41,7 @@ func (a *appTester) LazyInit(service service.PttService, obs observer.Observer)
|
|||||||
intro := widget.NewLabel("")
|
intro := widget.NewLabel("")
|
||||||
intro.Wrapping = fyne.TextWrapWord
|
intro.Wrapping = fyne.TextWrapWord
|
||||||
caseContent := container.NewBorder(
|
caseContent := container.NewBorder(
|
||||||
container.NewVBox(container.NewHBox(title, widget.NewSeparator(), widget.NewButton("压测", nil)), widget.NewSeparator(), intro), nil, nil, nil, content)
|
container.NewVBox(title, widget.NewSeparator(), intro), nil, nil, nil, content)
|
||||||
|
|
||||||
setNav := func(t *model.TestCase) {
|
setNav := func(t *model.TestCase) {
|
||||||
defer a.progress.Hide()
|
defer a.progress.Hide()
|
||||||
@ -171,15 +170,3 @@ func (a *appTester) makeNav(setNav func(testCase *model.TestCase)) fyne.CanvasOb
|
|||||||
}
|
}
|
||||||
return container.NewBorder(nil, nil, nil, nil, tree)
|
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
|
|
||||||
}
|
|
||||||
|
@ -2,70 +2,30 @@ package ui
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/theme"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type mainMenu struct {
|
type mainMenu struct {
|
||||||
*fyne.MainMenu
|
*fyne.MainMenu
|
||||||
sysMenu *fyne.Menu
|
|
||||||
appMenus []*fyne.MenuItem
|
|
||||||
|
|
||||||
settingMenu *fyne.Menu
|
helpMenu *fyne.Menu
|
||||||
testingMenu *fyne.MenuItem
|
sysLog *fyne.MenuItem
|
||||||
|
|
||||||
quite *fyne.MenuItem
|
|
||||||
|
|
||||||
helpMenu *fyne.Menu
|
|
||||||
sysLog *fyne.MenuItem
|
|
||||||
// aboutSelf *fyne.MenuItem
|
// aboutSelf *fyne.MenuItem
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMainMenu() *mainMenu {
|
// func newMainMenu() *mainMenu {
|
||||||
var mm mainMenu
|
// var mm mainMenu
|
||||||
|
|
||||||
// system
|
// // help
|
||||||
mm.appMenus = make([]*fyne.MenuItem, len(appRegister))
|
// mm.sysLog = fyne.NewMenuItem("Show Log", func() {
|
||||||
for i, app := range appRegister {
|
// newLogViewer().Win.Show()
|
||||||
app := app
|
// })
|
||||||
mm.appMenus[i] = fyne.NewMenuItem(app.GetAppName(), func() {
|
// mm.helpMenu = fyne.NewMenu("Help",
|
||||||
err := globalWin.at.openApp(app)
|
// mm.sysLog,
|
||||||
if err != nil {
|
// // mm.aboutSelf,
|
||||||
logrus.Errorf("打开 %s, err:%v", app.GetAppName(), err)
|
// )
|
||||||
}
|
|
||||||
})
|
|
||||||
mm.appMenus[i].Shortcut = app.ShortCut()
|
|
||||||
mm.appMenus[i].Icon = app.Icon()
|
|
||||||
}
|
|
||||||
|
|
||||||
mm.quite = fyne.NewMenuItem("退出", globalWin.quiteHandle)
|
// mm.MainMenu = fyne.NewMainMenu(
|
||||||
mm.quite.Icon = theme.LogoutIcon()
|
// mm.helpMenu,
|
||||||
mm.quite.IsQuit = true
|
// )
|
||||||
mm.sysMenu = fyne.NewMenu("应用", mm.appMenus...)
|
// return &mm
|
||||||
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
|
|
||||||
}
|
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"go_dreamfactory/cmd/v2/service"
|
"go_dreamfactory/cmd/v2/service"
|
||||||
"go_dreamfactory/cmd/v2/service/observer"
|
"go_dreamfactory/cmd/v2/service/observer"
|
||||||
"go_dreamfactory/comm"
|
"go_dreamfactory/comm"
|
||||||
"go_dreamfactory/lego/sys/log"
|
|
||||||
"go_dreamfactory/modules/user"
|
"go_dreamfactory/modules/user"
|
||||||
"go_dreamfactory/pb"
|
"go_dreamfactory/pb"
|
||||||
"strings"
|
"strings"
|
||||||
@ -21,11 +20,11 @@ import (
|
|||||||
"github.com/Pallinder/go-randomdata"
|
"github.com/Pallinder/go-randomdata"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
"golang.design/x/hotkey"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
globalWin *MainWindowImpl
|
globalWin *MainWindowImpl
|
||||||
|
toolWin *ToolWindowImpl
|
||||||
)
|
)
|
||||||
|
|
||||||
type MainWindow interface {
|
type MainWindow interface {
|
||||||
@ -35,13 +34,12 @@ type MainWindow interface {
|
|||||||
type MainWindowImpl struct {
|
type MainWindowImpl struct {
|
||||||
UIImpl
|
UIImpl
|
||||||
WindowDefaultOptions
|
WindowDefaultOptions
|
||||||
parent fyne.Window
|
parent fyne.Window
|
||||||
w fyne.Window
|
w fyne.Window
|
||||||
tb *toolBar //工具条
|
tb *toolBar //工具条
|
||||||
toys *toys // side
|
toys *toys // side
|
||||||
sb *statusBar //状态栏
|
sb *statusBar //状态栏
|
||||||
at *appContainer //tabs
|
at *appContainer //tabs
|
||||||
mm *mainMenu //菜单
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMainWindow(ui *UIImpl, parent fyne.Window) MainWindow {
|
func NewMainWindow(ui *UIImpl, parent fyne.Window) MainWindow {
|
||||||
@ -83,35 +81,27 @@ func (ui *MainWindowImpl) createWindowContainer() {
|
|||||||
// tool bar
|
// tool bar
|
||||||
toolbar := widget.NewToolbar(
|
toolbar := widget.NewToolbar(
|
||||||
widget.NewToolbarAction(theme.MediaVideoIcon(), func() {
|
widget.NewToolbarAction(theme.MediaVideoIcon(), func() {
|
||||||
openApp(ui.at, common.TOOLBAR_MONITOR)
|
openApp2(common.TOOLBAR_MONITOR)
|
||||||
}),
|
}),
|
||||||
widget.NewToolbarAction(theme.DocumentIcon(), func() {
|
widget.NewToolbarAction(theme.DocumentIcon(), func() {
|
||||||
openApp(ui.at, common.TOOLBAR_TESTER)
|
openApp2(common.TOOLBAR_TESTER)
|
||||||
}),
|
|
||||||
widget.NewToolbarAction(theme.StorageIcon(), func() {
|
|
||||||
openApp(ui.at, common.TOOLBAR_AUTO)
|
|
||||||
}),
|
}),
|
||||||
widget.NewToolbarSpacer(),
|
widget.NewToolbarSpacer(),
|
||||||
// widget.NewToolbarAction(theme.FileIcon(), func() {
|
widget.NewToolbarAction(theme.FileIcon(), func() {
|
||||||
// newLogViewer().Win.Show()
|
newLogViewer().Win.Show()
|
||||||
// }),
|
}),
|
||||||
)
|
)
|
||||||
ui.tb = newToolBar(toolbar)
|
ui.tb = newToolBar(toolbar)
|
||||||
|
|
||||||
// Fun Toys
|
// Fun Toys
|
||||||
ui.toys = newToys(ui.obs)
|
ui.toys = newToys(ui.obs)
|
||||||
|
|
||||||
// Main Menu
|
|
||||||
ui.mm = newMainMenu()
|
|
||||||
ui.w.SetMainMenu(ui.mm.MainMenu)
|
|
||||||
|
|
||||||
// main app tabs
|
// main app tabs
|
||||||
ui.at = newAppContainer(appRegister, ui.pttService, ui.obs)
|
ui.at = newAppContainer(appRegister, ui.pttService, ui.obs)
|
||||||
content := container.NewBorder(ui.tb.toolbar, ui.sb.widget, nil, ui.toys.widget, ui.at)
|
content := container.NewBorder(ui.tb.toolbar, ui.sb.widget, nil, ui.toys.widget, ui.at)
|
||||||
ui.w.SetContent(content)
|
ui.w.SetContent(content)
|
||||||
ui.w.CenterOnScreen()
|
ui.w.CenterOnScreen()
|
||||||
ui.w.SetCloseIntercept(ui.quiteHandle)
|
ui.w.SetCloseIntercept(ui.quiteHandle)
|
||||||
ui.registerShortCut()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ui *MainWindowImpl) SetStatusMsg(msg string) {
|
func (ui *MainWindowImpl) SetStatusMsg(msg string) {
|
||||||
@ -125,35 +115,7 @@ func (ui *MainWindowImpl) quiteHandle() {
|
|||||||
}
|
}
|
||||||
ui.app.Quit()
|
ui.app.Quit()
|
||||||
}, ui.w)
|
}, 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 ....
|
// CreateWindow ....
|
||||||
@ -207,7 +169,6 @@ func (ui *MainWindowImpl) createChooseServerPopUp(w fyne.Window) error {
|
|||||||
func (ui *MainWindowImpl) createChooseServerWindow(
|
func (ui *MainWindowImpl) createChooseServerWindow(
|
||||||
title string,
|
title string,
|
||||||
ch chan string) fyne.Window {
|
ch chan string) fyne.Window {
|
||||||
w := fyne.CurrentApp().NewWindow(title)
|
|
||||||
// choose server button func
|
// choose server button func
|
||||||
makeButton := func(s *service.ServiceConf, parent fyne.Window) *widget.Button {
|
makeButton := func(s *service.ServiceConf, parent fyne.Window) *widget.Button {
|
||||||
btn := widget.NewButton(s.Name, func() {
|
btn := widget.NewButton(s.Name, func() {
|
||||||
@ -222,12 +183,11 @@ func (ui *MainWindowImpl) createChooseServerWindow(
|
|||||||
dialog.ShowError(err, parent)
|
dialog.ShowError(err, parent)
|
||||||
} else {
|
} else {
|
||||||
ch <- fmt.Sprintf("%s:%s", s.SId, s.Name)
|
ch <- fmt.Sprintf("%s:%s", s.SId, s.Name)
|
||||||
w.Close()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return btn
|
return btn
|
||||||
}
|
}
|
||||||
|
w := fyne.CurrentApp().NewWindow(title)
|
||||||
sGrid := container.NewGridWithColumns(2)
|
sGrid := container.NewGridWithColumns(2)
|
||||||
config := ui.configService.GetConfig()
|
config := ui.configService.GetConfig()
|
||||||
if config != nil {
|
if config != nil {
|
||||||
@ -265,7 +225,7 @@ func (ui *MainWindowImpl) createLoginWin(sid, sname string) {
|
|||||||
if account.Text != "" {
|
if account.Text != "" {
|
||||||
logrus.WithField("account", account.Text).Debug("submit login")
|
logrus.WithField("account", account.Text).Debug("submit login")
|
||||||
ui.createWindowContainer()
|
ui.createWindowContainer()
|
||||||
appName, err := ui.at.openDefaultApp(common.TOOLBAR_MONITOR)
|
appName, err := ui.at.openDefaultApp()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithField("appName", appName).Error(err)
|
logrus.WithField("appName", appName).Error(err)
|
||||||
}
|
}
|
||||||
|
@ -1,114 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
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()
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
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()
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -20,10 +20,10 @@ func newToolBar(items *widget.Toolbar) *toolBar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// open app2
|
// open app2
|
||||||
func openApp(ac *appContainer, name string) {
|
func openApp2(name string) {
|
||||||
for _, app := range appRegister {
|
for _, app := range appRegister {
|
||||||
if app.GetAppName() == name {
|
if app.GetAppName() == name {
|
||||||
err := ac.openApp(app)
|
err := globalWin.at.openApp(app)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error(fmt.Errorf("%s %v", app.GetAppName(), err))
|
logrus.Error(fmt.Errorf("%s %v", app.GetAppName(), err))
|
||||||
}
|
}
|
||||||
@ -31,4 +31,13 @@ func openApp(ac *appContainer, 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,7 +15,7 @@ import (
|
|||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
"fyne.io/fyne/v2/dialog"
|
"fyne.io/fyne/v2/dialog"
|
||||||
"fyne.io/fyne/v2/layout"
|
"fyne.io/fyne/v2/layout"
|
||||||
fyne_storage "fyne.io/fyne/v2/storage"
|
"fyne.io/fyne/v2/storage"
|
||||||
"fyne.io/fyne/v2/theme"
|
"fyne.io/fyne/v2/theme"
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -401,7 +401,7 @@ func openFolder(entry *widget.Entry, w fyne.Window) {
|
|||||||
entry.Text = lu.Path()
|
entry.Text = lu.Path()
|
||||||
entry.Refresh()
|
entry.Refresh()
|
||||||
}, w)
|
}, w)
|
||||||
luri, _ := fyne_storage.ListerForURI(fyne_storage.NewFileURI("."))
|
luri, _ := storage.ListerForURI(storage.NewFileURI("."))
|
||||||
dConf.SetLocation(luri)
|
dConf.SetLocation(luri)
|
||||||
dConf.SetConfirmText("打开")
|
dConf.SetConfirmText("打开")
|
||||||
dConf.SetDismissText("取消")
|
dConf.SetDismissText("取消")
|
||||||
@ -419,7 +419,7 @@ func openFile(entry *widget.Entry, w fyne.Window) {
|
|||||||
}, w)
|
}, w)
|
||||||
dConf.SetConfirmText("打开")
|
dConf.SetConfirmText("打开")
|
||||||
dConf.SetDismissText("取消")
|
dConf.SetDismissText("取消")
|
||||||
dConf.SetFilter(fyne_storage.NewExtensionFileFilter([]string{".exe"}))
|
dConf.SetFilter(storage.NewExtensionFileFilter([]string{".exe"}))
|
||||||
dConf.Resize(fyne.NewSize(750, 500))
|
dConf.Resize(fyne.NewSize(750, 500))
|
||||||
dConf.Show()
|
dConf.Show()
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
"fyne.io/fyne/v2/dialog"
|
"fyne.io/fyne/v2/dialog"
|
||||||
"fyne.io/fyne/v2/layout"
|
"fyne.io/fyne/v2/layout"
|
||||||
fyne_storage "fyne.io/fyne/v2/storage"
|
"fyne.io/fyne/v2/storage"
|
||||||
"fyne.io/fyne/v2/theme"
|
"fyne.io/fyne/v2/theme"
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -47,7 +47,7 @@ func (this *appPbGen) LazyInit(ptService service.PttService, obs observer.Observ
|
|||||||
entry.Text = lu.Path()
|
entry.Text = lu.Path()
|
||||||
entry.Refresh()
|
entry.Refresh()
|
||||||
}, toolWin.w)
|
}, toolWin.w)
|
||||||
luri, _ := fyne_storage.ListerForURI(fyne_storage.NewFileURI("."))
|
luri, _ := storage.ListerForURI(storage.NewFileURI("."))
|
||||||
dConf.SetLocation(luri)
|
dConf.SetLocation(luri)
|
||||||
dConf.SetConfirmText("打开")
|
dConf.SetConfirmText("打开")
|
||||||
dConf.SetDismissText("取消")
|
dConf.SetDismissText("取消")
|
||||||
|
@ -40,19 +40,19 @@ type appTerm struct {
|
|||||||
downloadList *common.ItemList //download列表
|
downloadList *common.ItemList //download列表
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer) error {
|
func (this *appTerm) LazyInit(ptService service.PttService, obs observer.Observer) error {
|
||||||
app.obs = obs
|
this.obs = obs
|
||||||
app.sshService = &service.SSHService{}
|
this.sshService = &service.SSHService{}
|
||||||
app.jsonList = common.NewItemList()
|
this.jsonList = common.NewItemList()
|
||||||
|
|
||||||
//progress
|
//progress
|
||||||
app.cProgress = widget.NewProgressBarInfinite()
|
this.cProgress = widget.NewProgressBarInfinite()
|
||||||
app.cProgress.Hide()
|
this.cProgress.Hide()
|
||||||
|
|
||||||
app.upProgress = widget.NewProgressBar()
|
this.upProgress = widget.NewProgressBar()
|
||||||
app.upProgress.Hide()
|
this.upProgress.Hide()
|
||||||
|
|
||||||
app.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_TERM, theme.MailSendIcon(), nil)
|
this.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_TERM, theme.MailSendIcon(), nil)
|
||||||
content := container.NewMax()
|
content := container.NewMax()
|
||||||
content.Objects = []fyne.CanvasObject{}
|
content.Objects = []fyne.CanvasObject{}
|
||||||
|
|
||||||
@ -198,8 +198,8 @@ func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer
|
|||||||
|
|
||||||
// 连接
|
// 连接
|
||||||
connBtn.OnTapped = func() {
|
connBtn.OnTapped = func() {
|
||||||
app.cProgress.Show()
|
this.cProgress.Show()
|
||||||
app.cProgress.Start()
|
this.cProgress.Start()
|
||||||
ciphers := []string{}
|
ciphers := []string{}
|
||||||
|
|
||||||
if ip.Text == "" {
|
if ip.Text == "" {
|
||||||
@ -230,21 +230,21 @@ func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer
|
|||||||
}
|
}
|
||||||
connBtn.Disable()
|
connBtn.Disable()
|
||||||
|
|
||||||
err := app.sshService.Connect(userName.Text, password.Text, ip.Text, "", cast.ToInt(port.Text), ciphers)
|
err := this.sshService.Connect(userName.Text, password.Text, ip.Text, "", cast.ToInt(port.Text), ciphers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dialog.ShowError(err, toolWin.w)
|
dialog.ShowError(err, toolWin.w)
|
||||||
app.cProgress.Stop()
|
this.cProgress.Stop()
|
||||||
app.cProgress.Hide()
|
this.cProgress.Hide()
|
||||||
connBtn.Enable()
|
connBtn.Enable()
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
app.jsonList.LoadItem(localDir.Text)
|
this.jsonList.LoadItem(localDir.Text)
|
||||||
|
|
||||||
app.cProgress.Stop()
|
this.cProgress.Stop()
|
||||||
app.cProgress.Hide()
|
this.cProgress.Hide()
|
||||||
disConnBtn.Enable()
|
disConnBtn.Enable()
|
||||||
syncBtn.Enable()
|
syncBtn.Enable()
|
||||||
app.upProgress.Hide()
|
this.upProgress.Hide()
|
||||||
allCancelBtn.Show()
|
allCancelBtn.Show()
|
||||||
allSelBtn.Hide()
|
allSelBtn.Hide()
|
||||||
refreshBtn.Enable()
|
refreshBtn.Enable()
|
||||||
@ -260,7 +260,7 @@ func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer
|
|||||||
allSelBtn.Hide()
|
allSelBtn.Hide()
|
||||||
allCancelBtn.Show()
|
allCancelBtn.Show()
|
||||||
}()
|
}()
|
||||||
app.jsonList.LoadItem(localDir.Text)
|
this.jsonList.LoadItem(localDir.Text)
|
||||||
}
|
}
|
||||||
refreshBtn.OnTapped = reloadItem
|
refreshBtn.OnTapped = reloadItem
|
||||||
|
|
||||||
@ -268,7 +268,7 @@ func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer
|
|||||||
disConnBtn.Disable()
|
disConnBtn.Disable()
|
||||||
disConnBtn.OnTapped = func() {
|
disConnBtn.OnTapped = func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
app.jsonList.Reset()
|
this.jsonList.Reset()
|
||||||
connBtn.Enable()
|
connBtn.Enable()
|
||||||
disConnBtn.Disable()
|
disConnBtn.Disable()
|
||||||
syncBtn.Disable()
|
syncBtn.Disable()
|
||||||
@ -277,7 +277,7 @@ func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer
|
|||||||
refreshBtn.Disable()
|
refreshBtn.Disable()
|
||||||
dlBtn.Disable()
|
dlBtn.Disable()
|
||||||
}()
|
}()
|
||||||
app.sshService.Close()
|
this.sshService.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
//资源管理器
|
//资源管理器
|
||||||
@ -348,42 +348,42 @@ func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer
|
|||||||
syncNext := func() {
|
syncNext := func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
syncBtn.Enable()
|
syncBtn.Enable()
|
||||||
app.upProgress.Hide()
|
this.upProgress.Hide()
|
||||||
reloadItem()
|
reloadItem()
|
||||||
dialog.ShowInformation("提示", "所有文件均上传完毕,需等1-2分钟待文件热更", toolWin.w)
|
dialog.ShowInformation("提示", "所有文件均上传完毕,需等1-2分钟待文件热更", toolWin.w)
|
||||||
}()
|
}()
|
||||||
syncBtn.Disable()
|
syncBtn.Disable()
|
||||||
app.upProgress.Show()
|
this.upProgress.Show()
|
||||||
app.upProgress.SetValue(0)
|
this.upProgress.SetValue(0)
|
||||||
|
|
||||||
len := len(app.jsonList.SelItemIds)
|
len := len(this.jsonList.SelItemIds)
|
||||||
num := 0.0
|
num := 0.0
|
||||||
|
|
||||||
increment := func(wg *sync.WaitGroup) {
|
increment := func(wg *sync.WaitGroup) {
|
||||||
num += float64(1) / float64(len)
|
num += float64(1) / float64(len)
|
||||||
app.upProgress.SetValue(num)
|
this.upProgress.SetValue(num)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, fileName := range app.jsonList.SelItemIds {
|
for _, fileName := range this.jsonList.SelItemIds {
|
||||||
app.endProgress.Add(1)
|
this.endProgress.Add(1)
|
||||||
go func(fn string) {
|
go func(fn string) {
|
||||||
// time.Sleep(time.Second * time.Duration(rand.Intn(3)))
|
// time.Sleep(time.Second * time.Duration(rand.Intn(3)))
|
||||||
if err := app.sshService.ScpCopy(filepath.Join(localDir.Text, fn), remoteDir.Text); err != nil {
|
if err := this.sshService.ScpCopy(filepath.Join(localDir.Text, fn), remoteDir.Text); err != nil {
|
||||||
logrus.WithField("err", err).Error("同步json")
|
logrus.WithField("err", err).Error("同步json")
|
||||||
common.ShowTip(err.Error())
|
common.ShowTip(err.Error())
|
||||||
}
|
}
|
||||||
increment(&app.endProgress)
|
increment(&this.endProgress)
|
||||||
// 移除已上传的
|
// 移除已上传的
|
||||||
app.jsonList.DeleteItem(fn)
|
this.jsonList.DeleteItem(fn)
|
||||||
common.ShowTip(fmt.Sprintf("%s 成功上传", fn))
|
common.ShowTip(fmt.Sprintf("%s 成功上传", fn))
|
||||||
}(fileName)
|
}(fileName)
|
||||||
}
|
}
|
||||||
app.endProgress.Wait()
|
this.endProgress.Wait()
|
||||||
app.upProgress.SetValue(1)
|
this.upProgress.SetValue(1)
|
||||||
}
|
}
|
||||||
syncBtn.OnTapped = func() {
|
syncBtn.OnTapped = func() {
|
||||||
if app.sshService.Client == nil {
|
if this.sshService.Client == nil {
|
||||||
dialog.ShowError(errors.New("请先连接终端"), toolWin.w)
|
dialog.ShowError(errors.New("请先连接终端"), toolWin.w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -395,7 +395,7 @@ func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer
|
|||||||
svnBtn.FocusGained()
|
svnBtn.FocusGained()
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
if len(app.jsonList.SelItemIds) == 0 {
|
if len(this.jsonList.SelItemIds) == 0 {
|
||||||
common.ShowTip("没有选择任何文件,或尝试点击【刷新】")
|
common.ShowTip("没有选择任何文件,或尝试点击【刷新】")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -419,13 +419,13 @@ func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer
|
|||||||
// SVN更新
|
// SVN更新
|
||||||
svnNext := func() {
|
svnNext := func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
app.cProgress.Hide()
|
this.cProgress.Hide()
|
||||||
app.cProgress.Stop()
|
this.cProgress.Stop()
|
||||||
svnBtn.Enable()
|
svnBtn.Enable()
|
||||||
}()
|
}()
|
||||||
svnBtn.Disable()
|
svnBtn.Disable()
|
||||||
app.cProgress.Show()
|
this.cProgress.Show()
|
||||||
app.cProgress.Start()
|
this.cProgress.Start()
|
||||||
commandStr := `%s -h %s -j cfg -- -d %s --input_data_dir %s --output_data_dir %s --gen_types data_json -s server`
|
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,
|
arg := fmt.Sprintf(commandStr,
|
||||||
filepath.Join(workDir.Text, lubanCli.Text),
|
filepath.Join(workDir.Text, lubanCli.Text),
|
||||||
@ -465,12 +465,12 @@ func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer
|
|||||||
allCancelBtn.Hide()
|
allCancelBtn.Hide()
|
||||||
allSelBtn.Show()
|
allSelBtn.Show()
|
||||||
}()
|
}()
|
||||||
for i, v := range app.jsonList.CachedList.Items {
|
for i, v := range this.jsonList.CachedList.Items {
|
||||||
app.jsonList.CachedList.Items[i].Checked = true
|
this.jsonList.CachedList.Items[i].Checked = true
|
||||||
app.jsonList.SelItemIds = append(app.jsonList.SelItemIds, v.Text)
|
this.jsonList.SelItemIds = append(this.jsonList.SelItemIds, v.Text)
|
||||||
app.jsonList.ItemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
|
this.jsonList.ItemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
|
||||||
}
|
}
|
||||||
app.jsonList.ItemList.Refresh()
|
this.jsonList.ItemList.Refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 全选
|
// 全选
|
||||||
@ -479,18 +479,18 @@ func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer
|
|||||||
allCancelBtn.Show()
|
allCancelBtn.Show()
|
||||||
allSelBtn.Hide()
|
allSelBtn.Hide()
|
||||||
}()
|
}()
|
||||||
app.jsonList.SelItemIds = []string{}
|
this.jsonList.SelItemIds = []string{}
|
||||||
for i, v := range app.jsonList.CachedList.Items {
|
for i, v := range this.jsonList.CachedList.Items {
|
||||||
app.jsonList.CachedList.Items[i].Checked = false
|
this.jsonList.CachedList.Items[i].Checked = false
|
||||||
app.jsonList.ItemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
|
this.jsonList.ItemList.UpdateItem(i, widget.NewCheck(v.Text, nil))
|
||||||
}
|
}
|
||||||
app.jsonList.ItemList.Refresh()
|
this.jsonList.ItemList.Refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 搜索
|
// 搜索
|
||||||
searchEntry.PlaceHolder = "搜索"
|
searchEntry.PlaceHolder = "搜索"
|
||||||
searchEntry.OnChanged = func(s string) {
|
searchEntry.OnChanged = func(s string) {
|
||||||
if app.sshService.Client == nil {
|
if this.sshService.Client == nil {
|
||||||
dialog.ShowError(errors.New("请先连接终端"), toolWin.w)
|
dialog.ShowError(errors.New("请先连接终端"), toolWin.w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -499,13 +499,13 @@ func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer
|
|||||||
} else {
|
} else {
|
||||||
// go func() {
|
// go func() {
|
||||||
newList := []common.Item{}
|
newList := []common.Item{}
|
||||||
for _, v := range app.jsonList.SearchItem {
|
for _, v := range this.jsonList.SearchItem {
|
||||||
if strings.Contains(v.Text, s) {
|
if strings.Contains(v.Text, s) {
|
||||||
newList = append(newList, v)
|
newList = append(newList, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app.jsonList.CachedList.Items = newList
|
this.jsonList.CachedList.Items = newList
|
||||||
app.jsonList.ItemList.Refresh()
|
this.jsonList.ItemList.Refresh()
|
||||||
// }()
|
// }()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -513,7 +513,7 @@ func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer
|
|||||||
// 下载日志
|
// 下载日志
|
||||||
dlBtn.Disable()
|
dlBtn.Disable()
|
||||||
dlBtn.OnTapped = func() {
|
dlBtn.OnTapped = func() {
|
||||||
w := app.createDownloadWindow()
|
w := this.createDownloadWindow()
|
||||||
w.Show()
|
w.Show()
|
||||||
w.SetCloseIntercept(func() {
|
w.SetCloseIntercept(func() {
|
||||||
dlBtn.Enable()
|
dlBtn.Enable()
|
||||||
@ -523,19 +523,19 @@ func (app *appTerm) LazyInit(ptService service.PttService, obs observer.Observer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 创建json列表
|
// 创建json列表
|
||||||
app.jsonList.ItemList = app.jsonList.CreateDefaultCheckList()
|
this.jsonList.ItemList = this.jsonList.CreateDefaultCheckList()
|
||||||
|
|
||||||
btns1 := container.NewHBox(helpBtn1, dlBtn, &layout.Spacer{}, saveBtn1, connBtn, disConnBtn)
|
btns1 := container.NewHBox(helpBtn1, dlBtn, &layout.Spacer{}, saveBtn1, connBtn, disConnBtn)
|
||||||
btns2 := container.NewHBox(helpBtn2, &layout.Spacer{}, saveBtn2, excelBtn, svnBtn)
|
btns2 := container.NewHBox(helpBtn2, &layout.Spacer{}, saveBtn2, excelBtn, svnBtn)
|
||||||
|
|
||||||
split := container.NewHSplit(container.NewVBox(canvas.NewText("---只能在非上产环境!!!同步Json的操作仅限于数值热更,非结构热更---", color.RGBA{255, 0, 0, 255}), configForm,
|
split := container.NewHSplit(container.NewVBox(canvas.NewText("---只能在非上产环境!!!同步Json的操作仅限于数值热更,非结构热更---", color.RGBA{255, 0, 0, 255}), configForm,
|
||||||
btns1, svnForm, btns2, app.cProgress), container.NewBorder(
|
btns1, svnForm, btns2, this.cProgress), container.NewBorder(
|
||||||
container.NewBorder(nil, nil, container.NewHBox(allCancelBtn, allSelBtn, syncBtn, refreshBtn), container.NewHBox(explorBtn), searchEntry),
|
container.NewBorder(nil, nil, container.NewHBox(allCancelBtn, allSelBtn, syncBtn, refreshBtn), container.NewHBox(explorBtn), searchEntry),
|
||||||
nil, nil, nil, app.jsonList.ItemList))
|
nil, nil, nil, this.jsonList.ItemList))
|
||||||
split.Offset = 0.45
|
split.Offset = 0.45
|
||||||
content.Objects = append(content.Objects, container.NewBorder(nil, app.upProgress, nil, nil, split))
|
content.Objects = append(content.Objects, container.NewBorder(nil, this.upProgress, nil, nil, split))
|
||||||
|
|
||||||
app.tabItem.Content = content
|
this.tabItem.Content = content
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -52,8 +52,8 @@ func (a *appWelcome) GetAppName() string {
|
|||||||
return common.TOOLBAR_WEL
|
return common.TOOLBAR_WEL
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appWelcome) OpenDefault() string {
|
func (a *appWelcome) OpenDefault() bool {
|
||||||
return common.TOOLBAR_WEL
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appWelcome) ShortCut() fyne.Shortcut {
|
func (a *appWelcome) ShortCut() fyne.Shortcut {
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
var toolWin *ToolWindowImpl
|
|
||||||
type ToolWindow interface {
|
type ToolWindow interface {
|
||||||
WindowInterface
|
WindowInterface
|
||||||
}
|
}
|
||||||
@ -36,19 +36,19 @@ func NewToolWindow(ui *UIImpl, parent fyne.Window) ToolWindow {
|
|||||||
|
|
||||||
toolbar := widget.NewToolbar(
|
toolbar := widget.NewToolbar(
|
||||||
widget.NewToolbarAction(theme.ContentCopyIcon(), func() {
|
widget.NewToolbarAction(theme.ContentCopyIcon(), func() {
|
||||||
openApp(mw.at,common.TOOLBAR_GEN)
|
openApp1(common.TOOLBAR_GEN)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
widget.NewToolbarAction(theme.ContentAddIcon(), func() {
|
widget.NewToolbarAction(theme.ContentAddIcon(), func() {
|
||||||
openApp(mw.at,common.TOOLBAR_PB)
|
openApp1(common.TOOLBAR_PB)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
widget.NewToolbarAction(theme.DownloadIcon(), func() {
|
widget.NewToolbarAction(theme.DownloadIcon(), func() {
|
||||||
openApp(mw.at,common.TOOLBAR_SEC)
|
openApp1(common.TOOLBAR_SEC)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
widget.NewToolbarAction(theme.MailSendIcon(), func() {
|
widget.NewToolbarAction(theme.MailSendIcon(), func() {
|
||||||
openApp(mw.at,common.TOOLBAR_TERM)
|
openApp1(common.TOOLBAR_TERM)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
widget.NewToolbarSpacer(),
|
widget.NewToolbarSpacer(),
|
||||||
@ -59,16 +59,11 @@ func NewToolWindow(ui *UIImpl, parent fyne.Window) ToolWindow {
|
|||||||
|
|
||||||
mw.tb = newToolBar(toolbar)
|
mw.tb = newToolBar(toolbar)
|
||||||
|
|
||||||
mw.at = newAppContainer(appRegister, nil, ui.obs)
|
mw.at = newAppContainer(toolRegister, nil, ui.obs)
|
||||||
|
|
||||||
return mw
|
return mw
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ui *ToolWindowImpl) GetWin() WindowInterface {
|
|
||||||
return toolWin
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func (ui *ToolWindowImpl) CreateWindow(title string, width, height float32, _ bool) {
|
func (ui *ToolWindowImpl) CreateWindow(title string, width, height float32, _ bool) {
|
||||||
w := ui.app.NewWindow(fmt.Sprintf("工具箱 %s %s", title, ui.app.Metadata().Version))
|
w := ui.app.NewWindow(fmt.Sprintf("工具箱 %s %s", title, ui.app.Metadata().Version))
|
||||||
ui.AddWindow("tool", w)
|
ui.AddWindow("tool", w)
|
||||||
@ -78,7 +73,7 @@ func (ui *ToolWindowImpl) CreateWindow(title string, width, height float32, _ bo
|
|||||||
content := container.NewBorder(ui.tb.toolbar, ui.sb.widget,
|
content := container.NewBorder(ui.tb.toolbar, ui.sb.widget,
|
||||||
nil, nil, ui.at)
|
nil, nil, ui.at)
|
||||||
ui.w.SetContent(content)
|
ui.w.SetContent(content)
|
||||||
appName, err := ui.at.openDefaultApp(common.TOOLBAR_WEL)
|
appName, err := ui.at.openDefaultApp()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithField("appName", appName).Error(err)
|
logrus.WithField("appName", appName).Error(err)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go_dreamfactory/cmd/v2/lib/storage"
|
|
||||||
"go_dreamfactory/cmd/v2/service"
|
"go_dreamfactory/cmd/v2/service"
|
||||||
"go_dreamfactory/cmd/v2/service/observer"
|
"go_dreamfactory/cmd/v2/service/observer"
|
||||||
"go_dreamfactory/cmd/v2/theme"
|
"go_dreamfactory/cmd/v2/theme"
|
||||||
@ -10,7 +9,6 @@ import (
|
|||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"github.com/BabySid/gobase"
|
"github.com/BabySid/gobase"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var uid string
|
var uid string
|
||||||
@ -29,8 +27,6 @@ type UIImpl struct {
|
|||||||
pttService service.PttService
|
pttService service.PttService
|
||||||
configService service.ConfigService
|
configService service.ConfigService
|
||||||
obs observer.Observer
|
obs observer.Observer
|
||||||
storage storage.Storage
|
|
||||||
config *storage.Config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUI(app fyne.App,
|
func NewUI(app fyne.App,
|
||||||
@ -38,21 +34,8 @@ func NewUI(app fyne.App,
|
|||||||
connService service.ConnService,
|
connService service.ConnService,
|
||||||
pttService service.PttService,
|
pttService service.PttService,
|
||||||
obs observer.Observer,
|
obs observer.Observer,
|
||||||
) (*UIImpl, error) {
|
) *UIImpl {
|
||||||
app.Settings().SetTheme(&theme.MyTheme{})
|
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{
|
return &UIImpl{
|
||||||
app: app,
|
app: app,
|
||||||
windows: make(map[string]fyne.Window),
|
windows: make(map[string]fyne.Window),
|
||||||
@ -61,9 +44,7 @@ func NewUI(app fyne.App,
|
|||||||
connService: connService,
|
connService: connService,
|
||||||
pttService: pttService,
|
pttService: pttService,
|
||||||
obs: obs,
|
obs: obs,
|
||||||
storage: storage,
|
}
|
||||||
config: config,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ui *UIImpl) AddWindow(name string, w fyne.Window) {
|
func (ui *UIImpl) AddWindow(name string, w fyne.Window) {
|
||||||
|
@ -17,15 +17,15 @@ type BaseformView struct {
|
|||||||
service service.PttService
|
service service.PttService
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *BaseformView) Init(service service.PttService, obs observer.Observer, w fyne.Window, res *widget.Entry) {
|
func (this *BaseformView) Init(service service.PttService, obs observer.Observer, w fyne.Window, res *widget.Entry) {
|
||||||
view.service = service
|
this.service = service
|
||||||
view.obs = obs
|
this.obs = obs
|
||||||
view.w = w
|
this.w = w
|
||||||
view.res = res
|
this.res = res
|
||||||
view.form = widget.NewForm()
|
this.form = widget.NewForm()
|
||||||
view.form.SubmitText = common.BUTTON_OK
|
this.form.SubmitText = common.BUTTON_OK
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *BaseformView) Load() {
|
func (this *BaseformView) Load() {
|
||||||
view.form.OnSubmit()
|
this.form.OnSubmit()
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ type SociatyCreateView struct {
|
|||||||
BaseformView
|
BaseformView
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *SociatyCreateView) CreateView(t *model.TestCase) fyne.CanvasObject {
|
func (this *SociatyCreateView) CreateView(t *model.TestCase) fyne.CanvasObject {
|
||||||
sociatyName := widget.NewEntry()
|
sociatyName := widget.NewEntry()
|
||||||
notice := widget.NewMultiLineEntry()
|
notice := widget.NewMultiLineEntry()
|
||||||
icon := widget.NewEntry()
|
icon := widget.NewEntry()
|
||||||
@ -26,29 +26,26 @@ func (app *SociatyCreateView) CreateView(t *model.TestCase) fyne.CanvasObject {
|
|||||||
applyLv := widget.NewEntry()
|
applyLv := widget.NewEntry()
|
||||||
applyLv.Text = "1" //默认
|
applyLv.Text = "1" //默认
|
||||||
|
|
||||||
app.form.AppendItem(widget.NewFormItem("公会名称", sociatyName))
|
this.form.AppendItem(widget.NewFormItem("公会名称", sociatyName))
|
||||||
app.form.AppendItem(widget.NewFormItem("公告", notice))
|
this.form.AppendItem(widget.NewFormItem("公告", notice))
|
||||||
app.form.AppendItem(widget.NewFormItem("图标", icon))
|
this.form.AppendItem(widget.NewFormItem("图标", icon))
|
||||||
app.form.AppendItem(widget.NewFormItem("审批", isApplyCheck))
|
this.form.AppendItem(widget.NewFormItem("审批", isApplyCheck))
|
||||||
app.form.AppendItem(widget.NewFormItem("入会等级", applyLv))
|
this.form.AppendItem(widget.NewFormItem("入会等级", applyLv))
|
||||||
|
|
||||||
app.form.OnSubmit = func() {
|
this.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(
|
if err := service.GetPttService().SendToClient(
|
||||||
string(comm.ModuleSociaty),
|
string(comm.ModuleSociaty),
|
||||||
sociaty.SociatySubTypeCreate,
|
sociaty.SociatySubTypeCreate,
|
||||||
req,
|
&pb.SociatyCreateReq{
|
||||||
); err != nil {
|
Name: sociatyName.Text,
|
||||||
|
Icon: icon.Text,
|
||||||
|
Notice: notice.Text,
|
||||||
|
IsApplyCheck: isApplyCheck.Checked,
|
||||||
|
ApplyLv: cast.ToInt32(applyLv.Text),
|
||||||
|
}); err != nil {
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
}
|
}
|
||||||
logrus.WithFields(logrus.Fields{"mainType": string(comm.ModuleSociaty), "subType": sociaty.SociatySubTypeCreate, "params": req}).Info("创建工会")
|
|
||||||
}
|
}
|
||||||
app.form.SubmitText = "创建"
|
this.form.SubmitText = "创建"
|
||||||
return app.form
|
return this.form
|
||||||
}
|
}
|
||||||
|
@ -15,16 +15,14 @@ type SysFuncListView struct {
|
|||||||
|
|
||||||
func (this *SysFuncListView) CreateView(t *model.TestCase) fyne.CanvasObject {
|
func (this *SysFuncListView) CreateView(t *model.TestCase) fyne.CanvasObject {
|
||||||
this.form.OnSubmit = func() {
|
this.form.OnSubmit = func() {
|
||||||
req := &pb.SysFuncListReq{}
|
|
||||||
if err := service.GetPttService().SendToClient(
|
if err := service.GetPttService().SendToClient(
|
||||||
t.MainType,
|
t.MainType,
|
||||||
t.SubType,
|
t.SubType,
|
||||||
req,
|
&pb.SysFuncListReq{},
|
||||||
); err != nil {
|
); err != nil {
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logrus.WithFields(logrus.Fields{"mainType": t.MainType, "subType": t.SubType, "params": req}).Info("功能开启列表")
|
|
||||||
}
|
}
|
||||||
return this.form
|
return this.form
|
||||||
}
|
}
|
||||||
|
1
go.mod
1
go.mod
@ -178,7 +178,6 @@ require (
|
|||||||
go.opentelemetry.io/otel/trace v1.6.3 // indirect
|
go.opentelemetry.io/otel/trace v1.6.3 // indirect
|
||||||
go.uber.org/atomic v1.7.0 // indirect
|
go.uber.org/atomic v1.7.0 // indirect
|
||||||
go.uber.org/zap v1.17.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/crypto v0.0.0-20220829220503-c86fa9a7ed90
|
||||||
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd // indirect
|
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd // indirect
|
||||||
golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee // indirect
|
golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee // indirect
|
||||||
|
2
go.sum
2
go.sum
@ -845,8 +845,6 @@ 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 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=
|
||||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
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/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-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
Loading…
Reference in New Issue
Block a user