Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,67 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"engine.go",
"log.go",
"report.go",
],
importpath = "go-common/app/admin/main/aegis/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/aegis/model/common:go_default_library",
"//app/admin/main/aegis/model/net:go_default_library",
"//app/admin/main/aegis/model/resource:go_default_library",
"//app/admin/main/aegis/model/task:go_default_library",
"//app/service/main/account/api:go_default_library",
"//library/log:go_default_library",
"//library/time:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/admin/main/aegis/model/business:all-srcs",
"//app/admin/main/aegis/model/common:all-srcs",
"//app/admin/main/aegis/model/databus:all-srcs",
"//app/admin/main/aegis/model/middleware:all-srcs",
"//app/admin/main/aegis/model/monitor:all-srcs",
"//app/admin/main/aegis/model/net:all-srcs",
"//app/admin/main/aegis/model/resource:all-srcs",
"//app/admin/main/aegis/model/svg:all-srcs",
"//app/admin/main/aegis/model/task:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["model_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/aegis/model/common:go_default_library",
"//app/admin/main/aegis/model/resource:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,38 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"business.go",
"config.go",
],
importpath = "go-common/app/admin/main/aegis/model/business",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/aegis/model:go_default_library",
"//app/admin/main/aegis/model/common:go_default_library",
"//app/admin/main/aegis/model/middleware:go_default_library",
"//library/log:go_default_library",
"//library/time:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,217 @@
package business
import (
"fmt"
"reflect"
"strconv"
"strings"
"go-common/app/admin/main/aegis/model"
"go-common/app/admin/main/aegis/model/common"
"go-common/library/log"
xtime "go-common/library/time"
)
const (
// StateEnable 正常
StateEnable = int8(0)
// StateDisable 删除
StateDisable = int8(1)
// TypeIframe .
TypeIframe = int8(0)
// TypeSubmit 提交接口配置
TypeSubmit = int8(1)
// TypeAction 预留给前端组件配置
TypeAction = int8(2)
// TypeManagerBID 角色配置
TypeManagerBID = int8(3)
// TypeReverse 保留字配置
TypeReverse = int8(4)
// TypeAttribute 属性位配置
TypeAttribute = int8(5)
// TypeDeleteState 删除状态配置
TypeDeleteState = int8(6)
// TypeFiler 敏感词过滤
TypeFiler = int8(7)
// TypeBizBID 业务级别用户角色
TypeBizBID = int8(8)
// TypeAdapter 适配器配置
TypeAdapter = int8(9)
// TypeRscListAdapter 资源列表适配器
TypeRscListAdapter = int8(10)
// 中间件配置,用于前后端交互的自定义数据逻辑处理
TypeMiddleware = int8(11)
// TypeTempCodes 临时错误码
TypeTempCodes = int8(12)
// TypeCallback TODO 提交接口v2版本为了兼容线上的TypeSubmit。待v2上线后再去掉该配置改为TypeSubmit
TypeCallback = int8(13)
// MngBIDMID 任务用户角色: {"manager_id":1, "flow_id":12}
MngBIDMID = "manager_id"
// MngBIDFlow .
MngBIDFlow = "flow_id"
// BizBIDMngID 业务用户角色: {"manager_id":1, "admin":12}
BizBIDMngID = "manager_id"
// BizBIDAdmin .
BizBIDAdmin = "admin"
// AccessBiz .
AccessBiz = "access_biz"
// AccessFlow .
AccessFlow = "access_flow"
)
// Business .
type Business struct {
ID int64 `json:"id" gorm:"primary_key" form:"id"`
TP int64 `json:"type" gorm:"column:type" form:"type"`
Name string `json:"name" gorm:"column:name" form:"name" validate:"max=10"`
Desc string `json:"desc" gorm:"column:desc" form:"desc" validate:"max=160"`
Developer string `json:"developer" gorm:"column:developer" form:"developer"`
UID int64 `json:"uid" gorm:"column:uid"`
Attribute int64 `json:"attribute" gorm:"column:attribute" form:"attribute"`
State int64 `json:"state" gorm:"column:state" form:"state"`
UserName string `json:"username" gorm:"-"`
Ctime xtime.Time `json:"ctime" gorm:"column:ctime"`
Mtime xtime.Time `json:"mtime" gorm:"column:mtime"`
}
// IAdapter .
type IAdapter interface {
AdaptString(val string) string
AdaptInt64(val int64) int64
}
// Adapter 业务适配器
type Adapter struct {
Name string `json:"name"`
Rule string `json:"rule"`
Value string `json:"value"`
Compare string `json:"compare"`
}
// AdaptString .
func (a Adapter) AdaptString(val string) string {
return val
}
// AdaptInt .
func (a Adapter) AdaptInt(val int64) int64 {
switch a.Rule {
case "not":
if strconv.FormatInt(val, 10) != a.Compare {
if v, e := strconv.ParseInt(a.Value, 10, 64); e != nil {
log.Error("AdaptInt strconv.ParseInt(%s)", a.Value)
} else {
val = v
}
}
default:
log.Error("AdaptInt unsupported rule(%s)", a.Rule)
}
return val
}
// AdaptAddOpt ..
func AdaptAddOpt(opt *model.AddOption, adps []*Adapter) {
if len(adps) == 0 || opt == nil {
return
}
log.Info("AdaptAddOpt before opt(%+v)", opt)
v := reflect.ValueOf(opt).Elem()
for _, adp := range adps {
val := v.FieldByName(adp.Name)
if !val.CanSet() {
log.Error("AdaptAddOpt field(%s) can't set", adp.Name)
return
}
switch val.Kind() {
case reflect.String:
val.SetString(adp.AdaptString(val.String()))
case reflect.Int8, reflect.Int64, reflect.Int:
val.SetInt(adp.AdaptInt(val.Int()))
default:
log.Error("AdaptAddOpt unsupported adp(%+v) type(%v)", adp, val.Kind())
}
}
log.Info("AdaptAddOpt after opt(%+v)", opt)
}
// AdaptUpdateOpt ..
func AdaptUpdateOpt(opt *model.UpdateOption, adps []*Adapter) {
if len(adps) == 0 || opt == nil {
return
}
log.Info("AdaptUpdateOpt before opt(%+v)", opt)
for _, adp := range adps {
key := strings.ToLower(adp.Name)
if iv, ok := opt.Update[key]; ok {
switch reflect.TypeOf(iv).Kind() {
case reflect.String:
opt.Update[key] = adp.AdaptString(iv.(string))
case reflect.Int8, reflect.Int64, reflect.Int:
intv, err := strconv.Atoi(fmt.Sprint(iv))
if err != nil {
log.Error("AdaptUpdateOpt unsupported adp(%+v)", adp)
continue
}
opt.Update[key] = adp.AdaptInt(int64(intv))
default:
log.Error("AdaptUpdateOpt unsupported adp(%+v)", adp)
}
}
}
log.Info("AdaptUpdateOpt after opt(%+v)", opt)
}
// TableName .
func (t *Business) TableName() string {
return "business"
}
// OptList .
type OptList struct {
common.Pager
TP int8 `form:"type"`
}
// ListBusiness .
type ListBusiness struct {
common.Pager
Business []*Business `json:"business"`
}
// BizItem .
type BizItem struct {
BizID int64 `json:"business_id"`
BizName string `json:"business_name"`
BizType int64 `json:"biz_type"`
Flows map[int64]string `json:"flows"`
}
// FlowItem .
type FlowItem struct {
FlowID int64 `json:"flow_id"`
NetID int64 `json:"net_id"`
Name string `json:"name"`
ChName string `json:"ch_name"`
}
// BizItemArr .
type BizItemArr []*BizItem
func (a BizItemArr) Len() int {
return len(a)
}
func (a BizItemArr) Less(i, j int) bool {
return a[i].BizID < a[j].BizID
}
func (a BizItemArr) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}

View File

@@ -0,0 +1,87 @@
package business
import (
"encoding/json"
"go-common/app/admin/main/aegis/model/middleware"
"go-common/library/log"
xtime "go-common/library/time"
)
// BizCFG .
type BizCFG struct {
ID int64 `json:"id" gorm:"primary_key" form:"id"`
BusinessID int64 `json:"business_id" gorm:"column:business_id" form:"business_id"`
TP int8 `json:"type" gorm:"column:type" form:"type"`
Config string `json:"config" gorm:"column:config" form:"config"`
State int64 `json:"state" gorm:"column:state" form:"state"`
Ctime xtime.Time `json:"ctime" gorm:"column:ctime"`
Mtime xtime.Time `json:"mtime" gorm:"column:mtime"`
}
// TableName .
func (t *BizCFG) TableName() string {
return "business_config"
}
// FormatMngBID .
func (t *BizCFG) FormatMngBID() (biz int64, roles map[int64][]int64, err error) {
var (
cfgs []map[string]int64
)
if t.TP != TypeManagerBID || t.Config == "" {
return
}
biz = t.BusinessID
roles = map[int64][]int64{}
if err = json.Unmarshal([]byte(t.Config), &cfgs); err != nil {
log.Error("FormatMngBID json.Unmarshal(%+v) error(%v)", t, err)
return
}
for _, item := range cfgs {
if item[MngBIDMID] <= 0 || item[MngBIDFlow] <= 0 {
continue
}
if _, exist := roles[item[MngBIDMID]]; !exist {
roles[item[MngBIDMID]] = []int64{}
}
roles[item[MngBIDMID]] = append(roles[item[MngBIDMID]], item[MngBIDFlow])
}
return
}
// FormatBizBID .
func (t *BizCFG) FormatBizBID() (biz int64, roles map[string]int64, err error) {
if t.TP != TypeBizBID || t.Config == "" {
return
}
biz = t.BusinessID
if err = json.Unmarshal([]byte(t.Config), &roles); err != nil {
log.Error("FormatBizBID json.Unmarshal(%+v) error(%v)", t, err)
}
return
}
//FormatAggregate 聚合配置
func (t *BizCFG) FormatAggregate() (cfgs []*middleware.Aggregate, err error) {
if t.TP != TypeMiddleware || t.Config == "" {
return
}
cfgs = []*middleware.Aggregate{}
if err = json.Unmarshal([]byte(t.Config), &cfgs); err != nil {
log.Error("FormatAggregate json.Unmarshal error(%+v)", err)
}
return
}
// ManagerRole .
type ManagerRole struct {
FlowID int64 `json:"flow_id"`
MngBid int64 `json:"manager_bid"`
}

View File

@@ -0,0 +1,37 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = ["common.go"],
importpath = "go-common/app/admin/main/aegis/model/common",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["common_test.go"],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = ["//vendor/github.com/smartystreets/goconvey/convey:go_default_library"],
)

View File

@@ -0,0 +1,203 @@
package common
import (
"database/sql/driver"
"fmt"
"regexp"
"strconv"
"time"
)
// TimeFormat time format
var TimeFormat = "2006-01-02 15:04:05"
//GrayField gray config for each business
type GrayField struct {
Name string
Value string
}
// Pager .
type Pager struct {
Total int `json:"total" reflect:"ignore"`
Pn int `form:"pn" default:"1" json:"pn" reflect:"ignore"`
Ps int `form:"ps" default:"20" json:"ps" reflect:"ignore"`
}
// BaseOptions 公共参数
type BaseOptions struct {
BusinessID int64 `form:"business_id" json:"business_id"`
NetID int64 `form:"net_id" json:"net_id"`
FlowID int64 `form:"flow_id" json:"flow_id"`
UID int64 `form:"uid" json:"uid" submit:"int"`
OID string `form:"oid" json:"oid" submit:"string"`
RID int64 `form:"rid" json:"rid"`
Role int8 `form:"role" json:"role"`
Debug int8 `form:"debug" json:"debug"`
Uname string `form:"uname" json:"uname" submit:"string"`
}
// FormatTime .
type FormatTime string
// Scan .
func (f *FormatTime) Scan(src interface{}) (err error) {
switch sc := src.(type) {
case time.Time:
*f = FormatTime(sc.Format("2006-01-02 15:04:05"))
case string:
*f = FormatTime(sc)
}
return
}
// WaitTime 计算等待时长
func WaitTime(ctime time.Time) string {
wt := time.Since(ctime)
h := int(wt.Hours())
m := int(wt.Minutes()) % 60
s := int(wt.Seconds()) % 60
return fmt.Sprintf("%.2d:%.2d:%.2d", h, m, s)
}
//ParseWaitTime 。
func ParseWaitTime(ut int64) string {
h := ut / 3600
m := ut % 3600 / 60
s := ut % 60
return fmt.Sprintf("%.2d:%.2d:%.2d", h, m, s)
}
// Group .
type Group struct {
ID int64 `json:"group_id"`
Name string `json:"group_name"`
Note string `json:"group_note"`
Tag string `json:"group_tag"`
FontColor string `json:"font_color"`
BgColor string `json:"bg_color"`
}
// IntTime .
type IntTime int64
// Scan scan time.
func (jt *IntTime) Scan(src interface{}) (err error) {
switch sc := src.(type) {
case time.Time:
*jt = IntTime(sc.Unix())
case string:
var i int64
i, err = strconv.ParseInt(sc, 10, 64)
*jt = IntTime(i)
}
return
}
// Value get time value.
func (jt IntTime) Value() (driver.Value, error) {
return time.Unix(int64(jt), 0), nil
}
// Time get time.
func (jt IntTime) Time() time.Time {
return time.Unix(int64(jt), 0)
}
// UnmarshalJSON implement Unmarshaler
func (jt *IntTime) UnmarshalJSON(data []byte) error {
if data == nil || len(data) <= 1 {
*jt = 0
return nil
}
if data[0] != '"' {
// 1.直接判断数字
sti, err := strconv.Atoi(string(data))
if err == nil {
*jt = IntTime(sti)
}
return nil
}
str := string(data[1 : len(data)-1])
// 2.标准格式判断
st, err := time.ParseInLocation("2006-01-02 15:04:05", str, time.Local)
if err == nil {
*jt = IntTime(st.Unix())
return nil
}
*jt = IntTime(0)
return nil
}
// FilterName .
func FilterName(s string) (res string) {
exp := "[^a-zA-Z0-9_]+"
reg, err := regexp.Compile(exp)
if err != nil {
res = s
return
}
res = reg.ReplaceAllString(s, "")
return
}
// FilterChname .
func FilterChname(s string) (res string) {
exp := "[^0-9_\u4e00-\u9fa5]+"
reg, err := regexp.Compile(exp)
if err != nil {
res = s
return
}
res = reg.ReplaceAllString(s, "")
return
}
// FilterBusinessName .
func FilterBusinessName(s string) (res string) {
exp := "[^a-zA-Z\u4e00-\u9fa5]+"
reg, err := regexp.Compile(exp)
if err != nil {
res = s
return
}
res = reg.ReplaceAllString(s, "")
return
}
//Unique remove duplicated value from slice
func Unique(ids []int64, gthan0 bool) (res []int64) {
res = []int64{}
mm := map[int64]int64{}
for _, id := range ids {
if mm[id] == id || (gthan0 && id <= 0) {
continue
}
res = append(res, id)
mm[id] = id
}
return
}
//CopyMap copy src to dest
func CopyMap(src, dest map[int64][]int64, gthan0 bool) (res map[int64][]int64) {
if dest == nil {
dest = map[int64][]int64{}
}
for k, v := range src {
dest[k] = append(dest[k], v...)
dest[k] = Unique(dest[k], gthan0)
}
res = dest
return
}

View File

@@ -0,0 +1,97 @@
package common
import (
"github.com/smartystreets/goconvey/convey"
"testing"
"time"
)
func TestFormatTime_Scan(t *testing.T) {
convey.Convey("FormatTime_Scan", t, func(ctx convey.C) {
a := FormatTime("2018-01-01 01:00:00")
b := time.Time{}
err := a.Scan(b)
ctx.Convey("FormatTime_Scan", func(ctx convey.C) {
convey.So(err, convey.ShouldBeNil)
})
})
}
func TestWaitTime(t *testing.T) {
convey.Convey("WaitTime", t, func(ctx convey.C) {
b := time.Time{}
WaitTime(b)
})
}
func TestParseWaitTime(t *testing.T) {
convey.Convey("ParseWaitTime", t, func(ctx convey.C) {
b := time.Time{}.Unix()
ParseWaitTime(b)
})
}
var s = IntTime(time.Now().Unix())
func TestIntTime_Scan(t *testing.T) {
convey.Convey("IntTime_Scan", t, func(ctx convey.C) {
b := time.Time{}
err := s.Scan(&b)
ctx.Convey("IntTime_Scan", func(ctx convey.C) {
convey.So(err, convey.ShouldBeNil)
})
})
}
func TestIntTime_Value(t *testing.T) {
convey.Convey("IntTime_Value", t, func(ctx convey.C) {
s.Value()
})
}
func TestIntTime_UnmarshalJSON(t *testing.T) {
convey.Convey("IntTime_UnmarshalJSON", t, func(ctx convey.C) {
err := s.UnmarshalJSON(nil)
ctx.Convey("IntTime_UnmarshalJSON", func(ctx convey.C) {
convey.So(err, convey.ShouldBeNil)
})
})
}
func TestFilterName(t *testing.T) {
convey.Convey("FilterName", t, func(ctx convey.C) {
a := FilterName("hahah一个")
convey.So(a, convey.ShouldEqual, "hahah")
})
}
func TestFilterChname(t *testing.T) {
convey.Convey("FilterChname", t, func(ctx convey.C) {
a := FilterChname("hahah一个")
convey.So(a, convey.ShouldEqual, "一个")
})
}
func TestFilterBusinessName(t *testing.T) {
convey.Convey("FilterBusinessName", t, func(ctx convey.C) {
a := FilterBusinessName("hahah一个")
convey.So(a, convey.ShouldEqual, "hahah一个")
})
}
func TestUnique(t *testing.T) {
convey.Convey("Unique", t, func(ctx convey.C) {
b := []int64{1, -1, 0, 1, 1}
a := Unique(b, true)
convey.So(len(a), convey.ShouldEqual, 1)
convey.So(a[0], convey.ShouldEqual, 1)
})
}
func TestCopyMap(t *testing.T) {
convey.Convey("CopyMap", t, func(ctx convey.C) {
b := map[int64][]int64{}
a := CopyMap(map[int64][]int64{1: []int64{1}}, b, true)
convey.So(len(a), convey.ShouldEqual, 1)
})
}

View File

@@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["messages.go"],
importpath = "go-common/app/admin/main/aegis/model/databus",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,9 @@
package databus
// CreateTaskMsg .
type CreateTaskMsg struct {
BizID int64 `json:"business_id"`
RID int64 `json:"rid"`
FlowID int64 `json:"flow_id"`
DispatchLimit int64 `json:"dispatch_limit"`
}

View File

@@ -0,0 +1,360 @@
package model
import (
"encoding/json"
"fmt"
"reflect"
"go-common/app/admin/main/aegis/model/common"
"go-common/app/admin/main/aegis/model/net"
"go-common/app/admin/main/aegis/model/resource"
"go-common/app/admin/main/aegis/model/task"
member "go-common/app/service/main/account/api"
"go-common/library/log"
)
const (
// DefaultZeroInt form default zero
DefaultZeroInt = int64(-12345)
)
// EngineOption .
type EngineOption struct {
common.BaseOptions
TaskID int64 `json:"task_id" form:"task_id"`
Result *resource.Result `json:"resource_result" form:"resource_result" submit:"object"` // 资源的修改内容,要传就全传,否则传空
Forbid *Forbid `json:"forbid_params" submit:"json"`
ExtraData map[string]interface{} `json:"extra_data" submit:"map"`
}
// Forbid 封禁参数
type Forbid struct {
Notify int `json:"notify"`
Reason string `json:"reason"`
Duration int64 `json:"duration"`
Comment string `json:"comment"`
Img string `json:"img"`
}
// InfoResOption .
type InfoResOption struct {
common.BaseOptions
}
// ListResOption .
type ListResOption struct {
common.Pager
common.BaseOptions
BusinessID int64 `form:"business_id"`
FlowID int64 `form:"flow_id"`
}
// SubmitOptions 审核结果提交参数
type SubmitOptions struct {
EngineOption
NewFlowID int64 `json:"newflow_id"`
BindStr string `json:"binds"`
Binds []int64 `json:"-"`
}
// BatchOption 批量提交
type BatchOption struct {
BusinessID int64 `form:"business_id" json:"business_id" validate:"required"`
NetID int64 `form:"net_id" json:"net_id"`
UID int64 `form:"uid" json:"uid"`
Debug int8 `form:"debug" json:"debug"`
Uname string `form:"uname" json:"uname"`
RIDs []int64 `form:"rids,split" json:"rids" validate:"gt=0,dive,gt=0"`
Binds []int64 `form:"binds,split" json:"binds" validate:"gt=0,dive,gt=0"`
RejectReason string `form:"reject_reason"`
ReasonID int64 `form:"reason_id" default:"0"`
Notify int8 `form:"notify"`
}
// Tip 批量提交的错误提示
type Tip struct {
Success []int64 `json:"success"`
Async []int64 `json:"async"`
Fail map[int64]string `json:"fail"`
}
// AddOption add option
type AddOption struct {
resource.Resource
State int `form:"state" json:"state"`
NetID int64 `form:"net_id" json:"net_id" validate:"required"`
}
// UpdateKeys 可更新的资源字段
var UpdateKeys = map[string]struct{}{
"mid": {},
"content": {},
"extra1": {},
"extra2": {},
"extra3": {},
"extra4": {},
"extra5": {},
"extra6": {},
"extra1s": {},
"extra2s": {},
"extra3s": {},
"extra4s": {},
"extratime1": {},
"octime": {},
"ptime": {},
"metadata": {},
}
// UpdateOption update option
type UpdateOption struct {
BusinessID int64 `form:"business_id" json:"business_id" validate:"required"`
NetID int64 `form:"net_id" json:"net_id" validate:"required"`
OID string `form:"oid" json:"oid" validate:"required"`
Update map[string]interface{} `json:"update"`
}
// AuditInfo 审核详情页
type AuditInfo struct {
UnDoStat *task.UnDOStat `json:"undo_stat"`
Task *task.Task `json:"task"`
Flow *net.TransitionInfo `json:"flow"`
Resource *resource.Res `json:"resource"`
OperHistorys []string `json:"historys"`
IFrame string `json:"iframe_url,omitempty"`
UserInfo *UserInfo `json:"user_info"`
UserGroup map[int64]*common.Group `json:"user_group"`
Hit []string `json:"hit"`
Actions []*Action `json:"actions"`
}
// UserInfo .
type UserInfo struct {
Mid int64 `json:"mid"`
Name string `json:"name"`
Official member.OfficialInfo `json:"official"`
Follower int64 `json:"follower"`
}
// SyncMessage .
type SyncMessage struct {
URL string
Uname string `json:"auditor"`
MID int64 `json:"uid"`
OID string `json:"oid"`
RejectReason string `json:"reason"`
FlowData map[string]interface{} `json:"flow_data"`
ExtraData map[string]interface{} `json:"extra_data"`
ForbidParams map[string]interface{} `json:"forbid_params"`
Attribute map[string]int8 `json:"attribute"`
}
// GetEmptyInfo empty info for debug
func GetEmptyInfo() *AuditInfo {
info := &AuditInfo{
UnDoStat: &task.UnDOStat{},
Task: &task.Task{},
Flow: &net.TransitionInfo{
Operations: []*net.TranOperation{{}},
},
UserInfo: &UserInfo{},
Resource: &resource.Res{},
OperHistorys: []string{
"wulalalal",
},
IFrame: "iframe",
}
return info
}
// SearchParams ..
type SearchParams struct {
common.Pager
Debug int8 `form:"debug" reflect:"ignore"`
FilterOff bool `form:"state_filter_off" reflect:"ignore"`
BusinessID int64 `form:"business_id" validate:"required" reflect:"business_id"`
OID []string `form:"oid,split" reflect:"oid"`
FlowID int64 `form:"flow_id" default:"-12345" reflect:"flow_id,omitdefault"`
State int64 `form:"state" default:"-12345" reflect:"state,omitdefault"`
Mid int64 `form:"mid" default:"-12345" reflect:"mid,omitdefault"`
CtimeFrom string `form:"ctime_from" reflect:"ctime,from"`
CtimeTo string `form:"ctime_to" reflect:"ctime,to"`
Extra1 string `form:"extra1" reflect:"extra1" parse:"[]int"`
Extra2 string `form:"extra2" reflect:"extra2" parse:"int"`
Extra3 string `form:"extra3" reflect:"extra3" parse:"int"`
Extra4 string `form:"extra4" reflect:"extra4" parse:"int"`
Extra5 string `form:"extra4" reflect:"extra5" parse:"int"`
Extra6 string `form:"extra4" reflect:"extra6" parse:"int"`
Extra1s string `form:"extra1s" reflect:"extra1s" `
Extra2s string `form:"extra2s" reflect:"extra2s" `
Extra3s string `form:"extra3s" reflect:"extra3s" `
Extra4s string `form:"extra4s" reflect:"extra4s" `
ExtraTime1 string `form:"extratime1" reflect:"extratime1" ` //TODO 具体用到了再看怎么解析
KeyWord string `form:"keyWords" reflect:"ignore"`
CtimeOrder string `form:"ctime_order" reflect:"ignore"` //TODO 等octime导入后要按照octime筛选
}
// SearchRes search list.
type SearchRes struct {
Resources []*ListRscItem `json:"result"`
Page struct {
Num int `json:"num"`
Size int `json:"size"`
Total int `json:"total"`
} `json:"page"`
}
//Column .
type Column struct {
Name string `json:"name"`
ChName string `json:"chname"`
Enum map[int64]string `json:"enum,omitempty"`
}
// ListRscItem .
type ListRscItem struct {
resource.Res
FlowID int64 `json:"flow_id"`
UserInfo *UserInfo `json:"user_info"`
UserGroup map[int64]*common.Group `json:"user_group"`
Hit []string `json:"hit"`
}
// ListTaskItem .
type ListTaskItem struct {
ListTask
WaitTime string `json:"wait_time"`
OID string `json:"oid"`
Content string `json:"content"`
UserInfo *UserInfo `json:"user_info"`
UserGroup map[int64]*common.Group `json:"user_group"`
Metas map[string]interface{} `json:"metas"`
}
// ListTask 转化gtime
type ListTask struct {
*task.Task
GTstr string `json:"gtime"`
CTstr string `json:"ctime"`
MTstr string `json:"mtime"`
UserName string `json:"uid"`
MidStr string `json:"mid"`
}
// EmptyListItem .
func EmptyListItem() *ListRscItem {
return &ListRscItem{
UserInfo: &UserInfo{},
}
}
// IsImgType file type is image
func IsImgType(fileType string) bool {
return fileType != "image/jpeg" && fileType != "image/png" && fileType != "image/webp"
}
//Action 下发到前端的组件
type Action struct {
Name string `json:"name"`
URL string `json:"url"`
Method string `json:"method"`
Response string `json:"response"`
Extra string `json:"extra,omitempty"`
Params map[string]*ActionParam `json:"params"`
}
//ActionParam 烦人啊,动态的打回理由是必传参数
type ActionParam struct {
Value string `json:"value"`
Default string `json:"default"`
}
//SubReflect .
func SubReflect(ot reflect.Type, ov reflect.Value, key string, vals []string, defaultval string, params map[string]interface{}) {
var result string
boommsg := fmt.Sprintf("key:%s vals:%v ot:%+v vt:%+v", key, vals, ot, reflect.TypeOf(ov).Kind())
if len(vals) == 0 {
return
}
val := vals[0]
tfield, ok := ot.FieldByName(val)
if !ok {
log.Error("SubReflect1:" + boommsg)
return
}
vfield := ov.FieldByName(val)
if !vfield.IsValid() {
log.Error("SubReflect7:" + boommsg)
return
}
switch tfield.Tag.Get("submit") {
case "object":
vals = vals[1:]
tt := tfield.Type
vv := reflect.ValueOf(vfield)
if tfield.Type.Kind() == reflect.Ptr {
tt = tfield.Type.Elem()
vv = vfield.Elem()
}
SubReflect(tt, vv, key, vals, defaultval, params)
return
case "map":
if len(vals) != 2 || tfield.Type.Kind() != reflect.Map {
log.Error("SubReflect2:" + boommsg)
}
v := vfield.MapIndex(reflect.ValueOf(vals[1]))
if !v.IsValid() { //批量操作可能会没有map的参数
log.Warn("SubReflect4:" + boommsg)
return
}
result = fmt.Sprint(v.Interface())
case "json":
bs, err := json.Marshal(vfield.Interface())
if err != nil {
log.Error("SubReflect5:" + boommsg)
return
}
result = string(bs)
case "int", "string":
result = fmt.Sprint(vfield.Interface())
default:
log.Error("SubReflect6:" + boommsg)
}
if result == "" {
result = defaultval
}
params[key] = result
}
//Auth auth
type Auth struct {
OK bool `json:"ok"`
Admin bool `json:"admin"`
Business map[int64]int64 `json:"business"`
}
//UpsertItem 更新搜索的items
type UpsertItem struct {
ID int64 `json:"id"`
State int `json:"state"`
Extra1 int64 `json:"extra1"`
Extra2 int64 `json:"extra2"`
Extra3 int64 `json:"extra3"`
Extra4 int64 `json:"extra4"`
}
//CancelOption .
type CancelOption struct {
BusinessID int64 `form:"business_id" validate:"required" json:"business_id"`
Oids []string `form:"oids,split" validate:"required" json:"oids"`
Reason string `form:"reason" json:"reason"`
}

View File

@@ -0,0 +1,296 @@
package model
import (
"encoding/json"
"fmt"
"go-common/app/admin/main/aegis/model/net"
)
//..
const (
LogBusinessAudit = int(231)
LogTypeAuditSubmit = int(1)
LogTypeAuditJump = int(2)
LogTypeAuditAdd = int(3)
LogTypeAuditCancel = int(4)
LogBusinessTask = int(232)
LogTypeTaskDispatch = int(1)
LogTypeTaskConsumer = int(2)
LogTYpeTaskWeight = int(3)
LogBusinessResource = int(233)
LogTypeFormAuditor = int(1) // 审核员提交变更
LogTypeFromAdd = int(2) // 业务添加资源
LogTypeFromCancle = int(3) // 业务注销资源
LogBusinessNet = int(234) //流程流转
LogTypeNetTrigger = int(1) //流程流转
LogFromBatch = "批量提交"
LogFromSingle = "单个提交"
LogFromStart = "启动"
LogFromJump = "跳流程"
LogFromCancle = "取消流程"
LogBusinessNetConf = int(235) //流程配置
LogTypeNetConf = int(1) //流程网配置
LogTypeTokenConf = int(2) //令牌配置
LogTypeFlowConf = int(3) //节点配置
LogTypeTranConf = int(4) //变迁配置
LogTypeTokenBindConf = int(5) //令牌绑定配置
LogTypeDirConf = int(6) //有向线配置
//流程配置的操作
LogNetActionNew = "创建"
LogNetActionUpdate = "更新"
LogNetActionDisable = "禁用"
LogNetActionAvailable = "启用"
//流程配置的更新字段
LogFieldPID = "pid"
LogFieldChName = "ch_name"
LogFieldName = "name"
LogFieldTokenID = "token_id"
LogFieldStartFlow = "start_flow"
LogFieldTrigger = "trigger"
LogFieldLimit = "limit"
LogFieldDirection = "direction"
LogFieldOrder = "order"
LogFieldGuard = "guard"
LogFieldOutput = "output"
)
//LogFieldDesc 日志中的变更字段描述
var LogFieldDesc = map[string]string{
LogFieldPID: "父网",
LogFieldChName: "中文名",
LogFieldName: "英文名",
LogFieldTokenID: "令牌",
LogFieldStartFlow: "初始节点",
LogFieldTrigger: "触发类型",
LogFieldLimit: "限制",
LogFieldDirection: "指向",
LogFieldOrder: "顺序",
LogFieldGuard: "通行条件",
LogFieldOutput: "输出规则",
}
//LogFieldTemp 指定模板和字段,组建变更日志字段
func LogFieldTemp(field string, nw interface{}, old interface{}, diffTemp bool) (s string) {
var (
desc string
exist bool
temp string
)
if desc, exist = LogFieldDesc[field]; !exist {
desc = field
}
if diffTemp {
temp = "[%s]从[%v]变成[%v]"
s = fmt.Sprintf(temp, desc, old, nw)
} else {
temp = "[%s]为[%v]"
s = fmt.Sprintf(temp, desc, nw)
}
return
}
//NetConfOper 流程配置日志
type NetConfOper struct {
OID int64 `json:"oid"`
Action string `json:"action"`
UID int64 `json:"uid"`
Uname string `json:"uname"`
NetID int64 `json:"net_id"`
ChName string `json:"ch_name"`
FlowID int64 `json:"flow_id"`
TranID int64 `json:"tran_id"`
Diff []string `json:"diff"`
}
//SearchAuditLogParam 搜索行为日志参数
type SearchAuditLogParam struct {
RID []int64
OID []string `form:"oid,split" validate:"omitempty,max=30,dive,gt=0"`
Username []string `form:"username,split"`
CtimeFrom string `form:"ctime_from"`
CtimeTo string `form:"ctime_to"`
Ps int `form:"ps" validate:"gt=0,max=50" default:"10"`
Pn int `form:"pn" validate:"gt=0" default:"1"`
TaskID []int64 `form:"task_id,split" validate:"omitempty,max=30"`
State string `form:"state"`
BusinessID int64 `form:"business_id" validate:"required,gt=0"`
}
//SearchAuditLog 审核日志记录
type SearchAuditLog struct {
RID int64 `json:"rid"`
OID string `json:"oid"`
TaskID int64 `json:"task_id"`
State string `json:"state"`
Stime string `json:"stime"`
UID int64 `json:"uid"`
Uname string `json:"uname"`
Department string `json:"department"`
Extra string `json:"extra"`
}
type SearchLogResult struct {
Result []struct {
UID int64 `json:"uid"`
Uname string `json:"uname"`
OID int64 `json:"oid"`
Type int8 `json:"type"`
Action string `json:"action"`
Str0 string `json:"str_0"`
Str1 string `json:"str_1"`
Str2 string `json:"str_2"`
Int0 int64 `json:"int_0"`
Int1 int64 `json:"int_1"`
Int2 int64 `json:"int_2"`
Ctime string `json:"ctime"`
Extra string `json:"extra_data"`
} `json:"result"`
Page struct {
Num int `json:"num"`
Size int `json:"size"`
Total int `json:"total"`
} `json:"page"`
}
// Change for log
type Change struct {
Opt *SubmitOptions `json:"opt"`
Flow *Flow `json:"flow"`
}
//GetSubmitOper .
func (change *Change) GetSubmitOper() (flowaction, submitopt string) {
if change.Flow != nil && change.Flow.ResultToken != nil {
flowaction = change.Flow.ResultToken.ChName
}
if change.Opt != nil {
if change.Opt.Result != nil {
if change.Opt.Result.ReasonID != 0 {
submitopt += fmt.Sprintf(" 理由ID:%d ", change.Opt.Result.ReasonID)
}
if change.Opt.Result.RejectReason != "" && change.Opt.Result.RejectReason != "null" {
submitopt += fmt.Sprintf(" 打回理由:%s ", change.Opt.Result.RejectReason)
}
if change.Opt.Result.Note != "" && change.Opt.Result.Note != "null" {
submitopt += fmt.Sprintf(" 备注:%s ", change.Opt.Result.Note)
}
}
if change.Opt.Forbid != nil {
if change.Opt.Forbid.Reason != "" && change.Opt.Forbid.Reason != "null" {
submitopt += fmt.Sprintf(" 封禁理由:%s ", change.Opt.Forbid.Reason)
if du := change.Opt.Forbid.Duration; du == -1 {
submitopt += " 封禁时长:永久 "
} else {
submitopt += fmt.Sprintf(" 封禁时长:%d天 ", du/86400)
}
}
if change.Opt.Forbid.Comment != "" && change.Opt.Forbid.Comment != "null" {
submitopt += fmt.Sprintf(" 备注:%s ", change.Opt.Forbid.Comment)
}
}
}
return
}
// Flow for log
type Flow struct {
SubmitToken *net.TokenPackage `json:"submit_token"`
ResultToken *net.TokenPackage `json:"result_token"`
NewFlowID int64 `json:"new_flow_id"`
OldFlowID json.Number `json:"old_flow_id"`
}
// WeightLog task log
type WeightLog struct {
UPtime string `json:"uptime"`
Mid int64 `json:"mid"`
MemName string `json:"member_name"` // up主名称
Fans int64 `json:"fans"`
FansWeight int64 `json:"fans_weight"`
Group string `json:"group"`
GroupWeight int64 `json:"group_weight"`
WaitTime string `json:"wait_time"`
WaitWeight int64 `json:"wait_weight"`
EqualWeight int64 `json:"config_weight"`
ConfigItems []*ConfigItem `json:"config_items"`
Weight int64 `json:"weight"`
}
// ConfigItem .
type ConfigItem struct {
Name string `json:"name"`
Desc string `json:"desc"`
Username string `json:"uname"`
}
//TrackRsc 资源信息追踪
type TrackRsc struct {
Ctime string `json:"ctime"`
Content string `json:"content"`
Detail map[string]interface{} `json:"detail"`
}
//TrackAudit 操作日志信息追踪
type TrackAudit struct {
Ctime string `json:"ctime"`
FlowID []int64 `json:"flow_id"`
FlowName string `json:"flow_name"`
State string `json:"state"`
Uname string `json:"uname"`
}
//TrackInfo 信息追踪汇总
type TrackInfo struct {
Add []*TrackRsc `json:"add"`
Audit []*TrackAudit `json:"audit"`
Relation [][]int `json:"relation"`
}
//TrackParam 信息追踪参数
type TrackParam struct {
BusinessID int64 `form:"business_id" validate:"required,gt=0"`
OID string `form:"oid" validate:"required,gt=0"`
Pn int `form:"pn" validate:"gt=0" default:"1"`
Ps int `form:"ps" validate:"gt=0,max=30" default:"10"`
LastPageTime string `form:"last_page_time"`
}
//ParamsQueryLog .
type ParamsQueryLog struct {
Business int `reflect:"business"`
Type int `default:"0" reflect:"type,omitdefault"`
Uname []string `reflect:"uname"`
UID []int64 `reflect:"uid"`
Oid []int64 `reflect:"oid"`
Action []string `reflect:"action"`
CtimeFrom string `reflect:"ctime,from"`
CtimeTo string `reflect:"ctime,to"`
Int0 []int64 `reflect:"int_0"`
Int0From string `reflect:"int_0,from"`
Int0To string `reflect:"int_0,to"`
Int1 []int64 `reflect:"int_1"`
Int1From string `reflect:"int_1,from"`
Int1To string `reflect:"int_1,to"`
Int2 []int64 `reflect:"int_2"`
Int2From string `reflect:"int_2,from"`
Int3To string `reflect:"int_2,to"`
Str0 []string `reflect:"str_0"`
Str1 []string `reflect:"str_1"`
Str2 []string `reflect:"str_2"`
}
//EsCommon .
type EsCommon struct {
Pn int
Ps int
Order string
Sort string
Group string
}

View File

@@ -0,0 +1,48 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"config_test.go",
"response_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/admin/main/aegis/model:go_default_library",
"//app/admin/main/aegis/model/resource:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"config.go",
"response.go",
],
importpath = "go-common/app/admin/main/aegis/model/middleware",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = ["//library/log:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,163 @@
package middleware
import (
"fmt"
"reflect"
"sort"
"strconv"
"strings"
"go-common/library/log"
)
const (
//TypeMiddleAll 全部操作都允许
TypeMiddleAll = int8(0)
//TypeMiddleEncode 只允许编码,后端返回给前端的响应处理
TypeMiddleEncode = int8(1)
//TypeMiddleDecode 只允许解码,前端请求后端的请求参数处理
TypeMiddleDecode = int8(2)
)
//Aggregate 前端映射结构,对应于前后端交互的字段
type Aggregate struct {
Hitn string `json:"hitn"` //name的多个结构体用.表示分级
Hitv string `json:"hitv"` //枚举值
Mapn string `json:"mapn"` //映射字段名可以与hitname不同也可以相同
Mapv string `json:"mapv"` //映射字段值
Delimiter string `json:"delimiter"` //映射字段值的分隔符号
Order int64 `json:"order"` //顺序
Type int8 `json:"type"`
}
func (f *Aggregate) Process(data interface{}, encode bool) {
var (
field, fieldm reflect.Value
fieldExist, hited bool
)
defer func() {
if errs := recover(); errs != nil {
log.Error("Aggregate Process error(%+v)", errs)
}
}()
hitn := f.Hitn
hitv := strings.Split(f.Hitv, f.Delimiter)
mapn := f.Mapn
mapv := f.Mapv
if !encode {
hitn = f.Mapn
hitv = strings.Split(f.Mapv, f.Delimiter)
mapn = f.Hitn
mapv = f.Hitv
}
//check fields exist
fv := reflect.ValueOf(data)
if field, fieldExist = getFieldByName(fv, hitn); !fieldExist {
log.Warn("no field for hit(%s) data(%+v)", hitn, data)
return
}
if mapn == hitn {
fieldm = field
} else if fieldm, fieldExist = getFieldByName(fv, mapn); !fieldExist || !fieldm.CanSet() {
log.Warn("no field for map(%s) data(%+v)", mapn, data)
return
}
fieldv := fmt.Sprintf("%v", field.Interface())
for _, hit := range hitv {
if fieldv == hit {
hited = true
break
}
}
if !hited {
return
}
log.Info("got hit field(%s) value(%s) config(%+v)", hitn, fieldv, f)
switch fieldm.Kind() {
case reflect.String:
fieldm.SetString(mapv)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
vv, err := strconv.ParseInt(mapv, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", mapv, err)
return
}
fieldm.SetInt(vv)
default:
log.Warn("not support field.kind(%s) for field(%s)", fieldm.Kind().String(), mapn)
}
}
//getFieldByName 迭代遍历struct获取指定名字的字段
func getFieldByName(v reflect.Value, name string) (res reflect.Value, ok bool) {
tp := v.Type()
if tp.Kind() == reflect.Ptr {
v = v.Elem()
tp = tp.Elem()
}
if tp.Kind() != reflect.Struct || !v.IsValid() {
return
}
for i := 0; i < tp.NumField(); i++ {
fn := strings.ToLower(tp.Field(i).Name)
if fn == name {
res = v.Field(i)
ok = true
return
}
if vres, vok := getFieldByName(v.Field(i), name); vok {
ok = vok
res = vres
return
}
}
return
}
//MiddleAggregate 处理聚合逻辑
type MiddleAggregate struct {
Cfg []*Aggregate
Encode bool
}
//Process handle multi aggregate logists
func (m *MiddleAggregate) Process(data interface{}) {
cfgs := []*Aggregate{}
for _, item := range m.Cfg {
if item.Type == TypeMiddleAll || (m.Encode && item.Type == TypeMiddleEncode) || (!m.Encode && item.Type == TypeMiddleDecode) {
cfgs = append(cfgs, item)
}
}
if len(cfgs) == 0 {
return
}
sort.Sort(AggregateArr(cfgs))
for _, item := range cfgs {
item.Process(data, m.Encode)
}
}
//AggregateArr arr
type AggregateArr []*Aggregate
//Len .
func (f AggregateArr) Len() int {
return len(f)
}
//Less .
func (f AggregateArr) Less(i, j int) bool {
return f[i].Order < f[j].Order
}
//Swap .
func (f AggregateArr) Swap(i, j int) {
f[i], f[j] = f[j], f[i]
}

View File

@@ -0,0 +1,111 @@
package middleware
import (
"fmt"
"reflect"
"testing"
"github.com/smartystreets/goconvey/convey"
"go-common/app/admin/main/aegis/model"
"go-common/app/admin/main/aegis/model/resource"
)
var (
d = &Aggregate{
Hitn: "extra1",
Hitv: "2,3,4,5,6,7",
Mapn: "extra1",
Mapv: "2",
Order: 1,
}
ds = MiddleAggregate{
Cfg: []*Aggregate{d},
Encode: true,
}
)
func TestMiddleware_AggregateProcess(t *testing.T) {
var (
data = &model.AuditInfo{
Resource: &resource.Res{Extra1: 6},
}
encode bool = true
data2 = &model.SearchParams{
Extra1: "2",
}
)
convey.Convey("AggregateProcess", t, func(ctx convey.C) {
d.Process(data, encode) //将extra1=6替换成extra1=2
d.Process(data2, !encode) //将extra1=2替换成extra1=2,3,4,5,6,7
ctx.Convey("extra1 equal", func(ctx convey.C) {
ctx.So(fmt.Sprintf("%d", data.Resource.Extra1), convey.ShouldEqual, d.Mapv)
ctx.So(data2.Extra1, convey.ShouldEqual, d.Hitv)
})
})
}
func TestMiddlewaregetFieldByName(t *testing.T) {
var (
v = reflect.ValueOf(&model.AuditInfo{
Resource: &resource.Res{Extra1: 6},
})
name = "extra1"
)
convey.Convey("getFieldByName", t, func(ctx convey.C) {
res, ok := getFieldByName(v, name)
ctx.Convey("Then res,ok should not be nil.", func(ctx convey.C) {
ctx.So(ok, convey.ShouldEqual, true)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestMiddlewareProcess(t *testing.T) {
var (
data = &model.AuditInfo{
Resource: &resource.Res{Extra1: 6},
}
)
convey.Convey("Process", t, func(ctx convey.C) {
ds.Encode = true
ds.Process(data)
ctx.Convey("No return values", func(ctx convey.C) {
//将extra1=6替换成extra1=2
ctx.So(fmt.Sprintf("%d", data.Resource.Extra1), convey.ShouldEqual, d.Mapv)
})
})
}
func TestMiddlewareLen(t *testing.T) {
convey.Convey("Len", t, func(ctx convey.C) {
p1 := AggregateArr(ds.Cfg).Len()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldEqual, 1)
})
})
}
func TestMiddlewareLess(t *testing.T) {
var (
i = int(0)
j = int(0)
)
convey.Convey("Less", t, func(ctx convey.C) {
p1 := AggregateArr(ds.Cfg).Less(i, j)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldEqual, false)
})
})
}
func TestMiddlewareSwap(t *testing.T) {
var (
i = int(0)
j = int(0)
)
convey.Convey("Swap", t, func(ctx convey.C) {
AggregateArr(ds.Cfg).Swap(i, j)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
}

View File

@@ -0,0 +1,26 @@
package middleware
//IMiddleware handler
type IMiddleware interface {
Process(data interface{})
}
//ResponseRender .
type ResponseRender func(data interface{}, err error)
//Response response handler
func Response(data interface{}, err error, r ResponseRender, i IMiddleware) {
if data != nil && i != nil {
i.Process(data)
}
if r != nil {
r(data, err)
}
}
//Request request handler
func Request(data interface{}, i IMiddleware) {
if data != nil && i != nil {
i.Process(data)
}
}

View File

@@ -0,0 +1,44 @@
package middleware
import (
"testing"
"fmt"
"github.com/smartystreets/goconvey/convey"
"go-common/app/admin/main/aegis/model"
"go-common/app/admin/main/aegis/model/resource"
)
func TestMiddlewareRequest(t *testing.T) {
convey.Convey("Request", t, func(ctx convey.C) {
opt := new(model.SearchParams)
opt2 := &model.SearchParams{
Extra1: "2",
}
ds.Encode = false
Request(opt, &ds)
Request(opt2, &ds)
ctx.Convey("No return values", func(ctx convey.C) {
ctx.So(opt.Extra1, convey.ShouldEqual, "")
ctx.So(opt2.Extra1, convey.ShouldEqual, ds.Cfg[0].Hitv)
})
})
}
func TestMiddlewareResponse(t *testing.T) {
convey.Convey("Response", t, func(ctx convey.C) {
opt := new(model.AuditInfo)
opt2 := &model.AuditInfo{
Resource: &resource.Res{Extra1: 4},
}
ds.Encode = true
Response(opt, nil, nil, &ds)
Response(opt2, nil, nil, &ds)
ctx.Convey("No return values", func(ctx convey.C) {
ctx.So(opt.Resource, convey.ShouldBeNil)
ctx.So(fmt.Sprintf("%v", opt2.Resource.Extra1), convey.ShouldEqual, ds.Cfg[0].Mapv)
})
})
}

View File

@@ -0,0 +1,313 @@
package model
import (
"encoding/json"
"fmt"
"net/url"
"reflect"
"strings"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
"go-common/app/admin/main/aegis/model/common"
"go-common/app/admin/main/aegis/model/resource"
xtime "go-common/library/time"
)
func Test_SubmitOption(t *testing.T) {
sopt := &SubmitOptions{
EngineOption: EngineOption{
BaseOptions: common.BaseOptions{
BusinessID: 1,
FlowID: 1,
OID: "oid-123456",
RID: 1,
Uname: "cxf",
},
Forbid: &Forbid{
Comment: "dqqq",
Reason: "我的",
},
TaskID: 1,
Result: &resource.Result{
Attribute: 3,
Note: "哎",
RejectReason: "",
ReasonID: 3,
AttributeList: map[string]int8{
"no_comment": 1,
"no_forward": 0,
},
},
ExtraData: map[string]interface{}{
"mailto": "chenxuefeng",
"mail": 1,
"mid": 10086,
"notify": 1,
},
},
Binds: []int64{2, 3},
}
mapformat := map[string]*ActionParam{
"auditor": {
Value: "Uname",
},
"oid": {
Value: "OID",
},
"uid": {
Value: "ExtraData.mid",
},
"forbid_params": {
Value: "Forbid",
},
"no_comment": {
Value: "Result.AttributeList.no_comment",
},
"no_forward": {
Value: "Result.AttributeList.no_forward",
},
"notify": {
Value: "ExtraData.notify",
},
"reason": {
Value: "Result.RejectReason",
Default: " ",
},
}
ot := reflect.TypeOf(*sopt)
ov := reflect.ValueOf(*sopt)
params := make(map[string]interface{})
for k, v := range mapformat {
SubReflect(ot, ov, k, strings.Split(v.Value, "."), v.Default, params)
}
fmt.Println("params:", params)
values := url.Values{}
for k, v := range params {
values.Set(k, fmt.Sprint(v))
}
fmt.Println("values:", values.Encode())
t.Fail()
}
func Test_reflectMap(t *testing.T) {
mv := map[string]int8{"1": 1, "2": 2}
v := reflect.ValueOf(mv)
fmt.Println("a:", v.MapIndex(reflect.ValueOf("1")))
fmt.Println("b:", v.MapIndex(reflect.ValueOf("b")))
type A struct {
Name string
Age int
}
type B struct {
Info *A
Extra string
}
b := &B{
Info: &A{
Name: "name",
Age: 1,
},
Extra: "extra",
}
vbp := reflect.ValueOf(b)
vb := vbp.Elem()
fmt.Println("nb:", vb.FieldByName("Info").Elem().FieldByName("Name"))
bs, err := json.Marshal(vbp)
fmt.Println("bs1:", string(bs))
fmt.Println("err1:", err)
bs, err = json.Marshal(vbp.Interface())
fmt.Println("bs2:", string(bs))
fmt.Println("er2:", err)
t.Fail()
}
func Test_Report(t *testing.T) {
time1, _ := time.ParseInLocation("2006-01-02 15:04:05", "2018-11-29 11:11:28", time.Local)
time2 := time1.Add(+10 * time.Minute)
time3 := time1.Add(+2 * time.Hour)
time4 := time1.Add(+4 * time.Hour)
btime, _ := time.ParseInLocation("2006-01-02 15:04:05", "2018-11-29 11:00:00", time.Local)
etime, _ := time.ParseInLocation("2006-01-02 15:04:05", "2018-11-29 20:00:00", time.Local)
/*
1.同一小时内同用户
2.同一小时内不同用户
*/
metas := []*ReportMeta{
{Mtime: xtime.Time(time1.Unix()),
Content: `{"ds":4,"dy":1,"rl":2}`,
UID: 1,
Uname: "1",
},
{Mtime: xtime.Time(time2.Unix()),
Content: `{"ds":4,"rl":3}`,
UID: 1,
Uname: "1",
},
{Mtime: xtime.Time(time1.Unix()),
Content: `{"ds":4}`,
UID: 2,
Uname: "2",
},
{Mtime: xtime.Time(time2.Unix()),
Content: `{"ds":0,"st_3_225":1,"ut":0}`,
UID: 2,
Uname: "2",
},
{Mtime: xtime.Time(time3.Unix()),
Content: `{"ds":13,"dy":5,"rl":6,"rs_-1":1,"st_3_736":1,"st_4_0":2,"st_4_736":1,"ut":0}`,
UID: 1,
Uname: "1",
},
{Mtime: xtime.Time(time4.Unix()),
Content: `{"ds":2,"rs_1":1,"st_3_2":1,"ut":9}`,
UID: 2,
Uname: "2",
},
}
opt := &OptReport{
Btime: btime,
Etime: etime,
}
mnames := map[int64]string{
1: "1",
2: "2",
}
tempres := Gentempres(opt, mnames, metas)
bs1, _ := json.Marshal(tempres)
fmt.Printf("1: %s\n", string(bs1))
res := Genres(opt, tempres, mnames)
bs2, _ := json.Marshal(res)
fmt.Printf("2: %s\n", string(bs2))
form := Genform(res)
bs3, _ := json.Marshal(form)
fmt.Printf("3: %s\n", string(bs3))
t.Fail()
}
func Test_MemberStat(t *testing.T) {
time1, _ := time.ParseInLocation("2006-01-02 15:04:05", "2018-11-30 11:11:28", time.Local)
/*
1.处理量
2.处理率
3.通过率
4.平均耗时
*/
metas := []*ReportMeta{
{Mtime: xtime.Time(time1.Unix()),
Content: `{"ds":10,"dy":5,"rl":5,"rs_-1":1,"st_3_1":2,"st_4_0":2,"st_4_736":1,"ut":10}`,
UID: 1,
Uname: "1",
},
{Mtime: xtime.Time(time1.Unix()),
Content: `{"ds":5,"dy":5,"rl":5,"rs_-1":1,"rs_0":3,"st_3_1":2,"st_4_0":2,"st_4_736":1,"ut":10}`,
UID: 1,
Uname: "1",
},
{Mtime: xtime.Time(time1.Unix()),
Content: `{"ds":5,"dy":0,"rl":0,"rs_-1":1,"rs_0":3,"st_3_1":1,"st_4_0":2,"st_4_736":1,"ut":10}`,
UID: 1,
Uname: "1",
},
{Mtime: xtime.Time(time1.Unix()),
Content: `{"ds":0,"st_3_0":1,"ut":0} `,
UID: 2,
Uname: "2",
},
{Mtime: xtime.Time(time1.Unix()),
Content: `{"ds":0,"st_3_0":1,"ut":0}`,
UID: 2,
Uname: "2",
},
{Mtime: xtime.Time(time1.Unix()),
Content: `{"ds":5,"rs_0":5,"st_3_2":5,"ut":21}`,
UID: 2,
Uname: "2",
},
{Mtime: xtime.Time(time1.Unix()),
Content: `{"ds":2}`,
UID: 3,
Uname: "3",
},
{Mtime: xtime.Time(time1.Unix()),
Content: `{"ds":0,"rl":2}`,
UID: 3,
Uname: "3",
},
{Mtime: xtime.Time(time1.Unix()),
Content: `{"ds":0,"st_4_4":4,"ut":0} `,
UID: 4,
Uname: "4",
},
}
res, _ := GenMemberStat(metas, 0)
bs, _ := json.Marshal(res)
fmt.Printf("%s\n", string(bs))
t.Fail()
}
func Test_Column(t *testing.T) {
column := `[
{
"name":"id",
"chname":"呵呵"
},{
"name":"id2",
"chname":"呵呵",
"enum":{
"1":"上",
"2":"下"
}
}
]`
cs := []*Column{}
e := json.Unmarshal([]byte(column), &cs)
fmt.Println(e)
fmt.Printf("cs:%+v\n", cs)
t.Fail()
}
func TestLogFieldTemp(t *testing.T) {
s := LogFieldTemp(LogFieldPID, 1, 0, true)
convey.Convey("LogFieldTemp", t, func() {
convey.So(s, convey.ShouldNotEqual, "")
})
}
func TestGetEmptyInfo(t *testing.T) {
s := GetEmptyInfo()
convey.Convey("GetEmptyInfo", t, func() {
convey.So(s, convey.ShouldNotBeNil)
})
}
func TestEmptyListItem(t *testing.T) {
s := EmptyListItem()
convey.Convey("EmptyListItem", t, func() {
convey.So(s, convey.ShouldNotBeNil)
})
}

View File

@@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["monitor.go"],
importpath = "go-common/app/admin/main/aegis/model/monitor",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,64 @@
package monitor
const (
// RedisPrefix 参数:business。参数1bid参数2监控ID
RedisPrefix = "monitor_stats_%d"
// CompGT 大于
CompGT = ">"
// CompLT 小于
CompLT = "<"
)
// RuleResultData 返回的结果数据
type RuleResultData struct {
Rule *Rule `json:"rule"`
User *User `json:"user"`
Stats *Stats `json:"stats"`
}
// Rule 监控规则信息
type Rule struct {
ID int64 `json:"id"`
Type int8 `json:"type"`
BID int8 `json:"bid"`
Name string `json:"name"`
State int8 `json:"state"`
STime string `json:"stime"`
ETime string `json:"etime"`
CTime string `json:"ctime"`
MTime string `json:"mtime"`
UID int64 `json:"uid"`
RuleConf *RuleConf `json:"rule"`
}
// RuleConf 监控方案配置结构体
type RuleConf struct {
Name string `json:"name"`
MoniCdt map[string]struct { //监控方案的监控条件
Comp string `json:"comparison"`
Value int64 `json:"value"`
} `json:"moni_cdt"`
NotifyCdt map[string]struct { //达到发送通知的条件
Comp string `json:"comparison"`
Value int64 `json:"value"`
} `json:"notify_cdt"`
Notify struct { //通知类型配置
Way int8 `json:"way"`
Member []string `json:"member"`
} `json:"notify"`
}
// Stats 监控统计
type Stats struct {
TotalCount int `json:"total_count"`
MoniCount int `json:"moni_count"`
MaxTime int `json:"max_time"`
}
// User manager user struct
type User struct {
ID int64 `json:"id"`
UserName string `json:"username"`
NickName string `json:"nickname"`
}

View File

@@ -0,0 +1,40 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"direction.go",
"flow.go",
"flow_resource.go",
"net.go",
"params.go",
"token.go",
"transition.go",
],
importpath = "go-common/app/admin/main/aegis/model/net",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/aegis/model/common:go_default_library",
"//library/time:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,60 @@
package net
import (
"time"
)
const (
// TableDirection .
TableDirection = "net_direction"
//DirInput 从flow指向transition
DirInput = int8(1)
//DirOutput 从transition指向flow
DirOutput = int8(2)
//DirOrderSequence 下游顺序执行
DirOrderSequence = int8(0)
//DirOrderOrSplit 下游根据条件拆分各分支若为transition,可允许操作个数>=1
DirOrderOrSplit = int8(1)
//DirOrderOrResultSplit 下游transition操作拆分每个transition只有一个可允许操作enable均默认为true但只能操作一个
//先不做, 如果做了在详情页提交后怎么知道提交的是哪个transition有多个
DirOrderOrResultSplit = int8(2)
//todo --- 其他顺序 v2
)
// DirDirectionDesc .
var DirDirectionDesc = map[int8]string{
DirInput: "从节点指向变化",
DirOutput: "从变化指向节点",
}
// DirOrderDesc 有向线下游顺序描述
var DirOrderDesc = map[int8]string{
DirOrderSequence: "直序",
}
// Direction 有向线连接flow和transition
type Direction struct {
ID int64 `gorm:"primary_key" json:"id" form:"id" validate:"omitempty,gt=0"`
NetID int64 `gorm:"column:net_id" json:"net_id" form:"net_id" validate:"omitempty,gt=0"`
FlowID int64 `gorm:"column:flow_id" json:"flow_id" form:"flow_id" validate:"required,gt=0"`
TransitionID int64 `gorm:"column:transition_id" json:"transition_id" form:"transition_id" validate:"required,gt=0"`
Direction int8 `gorm:"column:direction" json:"direction" form:"direction" validate:"required,min=1,max=2"`
Order int8 `gorm:"column:order" json:"order" form:"order" validate:"omitempty,min=0,max=2"`
Guard string `gorm:"column:guard" json:"guard"`
Output string `gorm:"column:output" json:"output"`
UID int64 `gorm:"column:uid" json:"uid"`
DisableTime time.Time `gorm:"column:disable_time" json:"disable_time"`
Ctime time.Time `gorm:"column:ctime" json:"ctime"`
Mtime time.Time `gorm:"column:mtime" json:"mtime"`
}
// TableName .
func (d *Direction) TableName() string {
return TableDirection
}
// IsAvailable .
func (d *Direction) IsAvailable() bool {
return d.DisableTime.IsZero()
}

View File

@@ -0,0 +1,48 @@
package net
import (
"time"
)
const (
// TableFlow .
TableFlow = "net_flow"
)
// Flow 节点
type Flow struct {
ID int64 `gorm:"primary_key" json:"id"`
NetID int64 `gorm:"column:net_id" json:"net_id"`
Name string `gorm:"column:name" json:"name"`
ChName string `gorm:"column:ch_name" json:"ch_name"`
Description string `gorm:"column:description" json:"description"`
UID int64 `gorm:"column:uid" json:"uid"`
DisableTime time.Time `gorm:"column:disable_time" json:"disable_time"`
Ctime time.Time `gorm:"column:ctime" json:"ctime"`
Mtime time.Time `gorm:"column:mtime" json:"mtime"`
}
// TableName .
func (f *Flow) TableName() string {
return TableFlow
}
// IsAvailable .
func (f *Flow) IsAvailable() bool {
return f.DisableTime.IsZero()
}
// FlowArr .
type FlowArr []*Flow
func (a FlowArr) Len() int {
return len(a)
}
func (a FlowArr) Less(i, j int) bool {
return a[i].ID < a[j].ID
}
func (a FlowArr) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}

View File

@@ -0,0 +1,25 @@
package net
const (
//TableFlowResource .
TableFlowResource = "net_flow_resource"
//FRStateDeleted 流程取消状态
FRStateDeleted = -1
//FRStateRunning 流程运行状态
FRStateRunning = 0
)
//FlowResource 资源在审核网的运行现状
type FlowResource struct {
ID int64 `gorm:"primary_key" json:"id"`
RID int64 `gorm:"column:rid" json:"rid"`
FlowID int64 `gorm:"column:flow_id" json:"flow_id"`
State int8 `gorm:"column:state" json:"state"`
NetID int64 `gorm:"column:net_id" json:"net_id"`
}
// TableName .
func (fr *FlowResource) TableName() string {
return TableFlowResource
}

View File

@@ -0,0 +1,37 @@
package net
import (
"time"
)
const (
// TableNet .
TableNet = "net"
)
// Recovered .
var Recovered = time.Time{}
// Net net.
type Net struct {
ID int64 `gorm:"primary_key" json:"id" form:"id" validate:"omitempty,gt=0"`
BusinessID int64 `gorm:"column:business_id" json:"business_id" form:"business_id" validate:"omitempty,gt=0"`
ChName string `gorm:"column:ch_name" json:"ch_name" form:"ch_name" validate:"required,max=32"`
Description string `gorm:"column:description" json:"description" form:"description" validate:"max=60"`
StartFlowID int64 `gorm:"column:start_flow_id" json:"start_flow_id" form:"start_flow_id"`
PID int64 `gorm:"column:pid" json:"pid"`
UID int64 `gorm:"column:uid" json:"uid"`
DisableTime time.Time `gorm:"column:disable_time" json:"disable_time"`
Ctime time.Time `gorm:"column:ctime" json:"ctime"`
Mtime time.Time `gorm:"column:mtime" json:"mtime"`
}
//TableName table name
func (n *Net) TableName() string {
return TableNet
}
// IsAvailable .
func (n *Net) IsAvailable() bool {
return n.DisableTime.IsZero()
}

View File

@@ -0,0 +1,332 @@
package net
import (
"go-common/app/admin/main/aegis/model/common"
xtime "go-common/library/time"
)
const (
//StateAvailable .
StateAvailable = "available"
//StateDisable .
StateDisable = "disable"
)
// ListNetParam .
type ListNetParam struct {
BusinessID int64 `json:"business_id" form:"business_id" validte:"omitempty,gt=0"`
ID []int64 `json:"id" form:"id,split" validate:"omitempty,dive,gt=0"`
State string `json:"state" form:"state"`
Sort string `json:"sort" form:"sort" default:"desc"`
Pn int64 `json:"pn" form:"pn" default:"1" validate:"gt=0"`
Ps int64 `json:"ps" form:"ps" default:"30" validate:"gt=0"`
}
// ListNetItem .
type ListNetItem struct {
ID int64 `json:"id"`
BusinessID int64 `json:"business_id"`
ChName string `json:"ch_name"`
Description string `json:"description"`
StartFlowID int64 `json:"start_flow_id"`
PID int64 `json:"pid" gorm:"column:pid"`
UID int64 `json:"uid" gorm:"column:uid"`
DisableTime xtime.Time `json:"disable_time"`
Ctime common.FormatTime `json:"ctime"`
Mtime common.FormatTime `json:"mtime"`
BusinessName string `json:"business_name"`
Username string `json:"username"`
}
// ListNetRes .
type ListNetRes struct {
Result []*ListNetItem `json:"result"`
Pager Pager `json:"pager"`
}
// NetEditParam .
type NetEditParam struct {
ID int64 `form:"id" validate:"required,gt=0"`
ChName string `form:"ch_name" validate:"required,max=32"`
Description string `form:"description" validate:"max=60"`
}
// ListTokenParam .
type ListTokenParam struct {
NetID int64 `json:"net_id" form:"net_id" validate:"required,gt=0"`
Name string `json:"name" form:"name" validate:"omitempty,max=10"`
ID []int64 `json:"id" form:"id,split" validate:"omitempty,dive,gt=0"`
Sort string `json:"sort" form:"sort" default:"desc"`
Pn int64 `json:"pn" form:"pn" default:"1" validate:"gt=0"`
Ps int64 `json:"ps" form:"ps" default:"30" validate:"gt=0"`
Assign bool `json:"assign" form:"assign"`
}
// GroupTokenParam .
type GroupTokenParam struct {
BusinessID int64 `json:"business_id" form:"business_id" validate:"omitempty,gt=0"`
NetID int64 `json:"net_id" form:"net_id" validate:"omitempty,gt=0"`
GroupName string `json:"group_name" form:"group_name" validate:"omitempty,max=10"`
}
// ListTokenItem .
type ListTokenItem struct {
ID int64 `json:"id"`
NetID int64 `json:"net_id"`
ChName string `json:"ch_name"`
Name string `json:"name"`
Compare int8 `json:"compare"`
Value string `json:"value"`
Type int8 `json:"type"`
UID int64 `json:"uid" gorm:"column:uid"`
Ctime common.FormatTime `json:"ctime"`
Mtime common.FormatTime `json:"mtime"`
Username string `json:"username"`
}
// ListTokenRes .
type ListTokenRes struct {
Result []*ListTokenItem `json:"result"`
Pager Pager `json:"pager"`
}
// ListNetElementParam .
type ListNetElementParam struct {
NetID int64 `json:"net_id" form:"net_id" validate:"required,gt=0"`
Name string `json:"name" form:"name" validate:"omitempty,max=10"`
ID []int64 `json:"id" form:"id,split" validate:"omitempty,dive,gt=0"`
State string `json:"state" form:"state"`
Sort string `json:"sort" form:"sort" default:"desc"`
Pn int64 `json:"pn" form:"pn" default:"1" validate:"gt=0"`
Ps int64 `json:"ps" form:"ps" default:"30" validate:"gt=0"`
}
// ListFlowItem .
type ListFlowItem struct {
ID int64 `json:"id"`
NetID int64 `json:"net_id"`
Name string `json:"name"`
ChName string `json:"ch_name"`
Description string `json:"description"`
UID int64 `json:"uid" gorm:"column:uid"`
DisableTime xtime.Time `json:"disable_time"`
Ctime common.FormatTime `json:"ctime"`
Mtime common.FormatTime `json:"mtime"`
Username string `json:"username"`
Tokens []string `json:"tokens"`
IsStart bool `json:"is_start"`
}
// ListFlowRes .
type ListFlowRes struct {
Result []*ListFlowItem `json:"result"`
Pager Pager `json:"pager"`
}
// ListTransitionItem .
type ListTransitionItem struct {
ID int64 `json:"id"`
NetID int64 `json:"net_id"`
Trigger int8 `json:"trigger"`
Limit int64 `json:"limit"`
Name string `json:"name"`
ChName string `json:"ch_name"`
Description string `json:"description"`
UID int64 `json:"uid" gorm:"column:uid"`
DisableTime xtime.Time `json:"disable_time"`
Ctime common.FormatTime `json:"ctime"`
Mtime common.FormatTime `json:"mtime"`
Username string `json:"username"`
Tokens []string `json:"tokens"`
}
// ListTransitionRes .
type ListTransitionRes struct {
Result []*ListTransitionItem `json:"result"`
Pager Pager `json:"pager"`
}
// ListDirectionParam .
type ListDirectionParam struct {
NetID int64 `json:"net_id" form:"net_id" validate:"required,gt=0"`
FlowID int64 `json:"flow_id" form:"flow_id" validate:"omitempty,gt=0"`
TransitionID int64 `json:"transition_id" form:"transition_id" validate:"omitempty,gt=0"`
Direction int8 `json:"direction" form:"direction"`
ID []int64 `json:"id" form:"id,split" validate:"omitempty,dive,gt=0"`
State string `json:"state" form:"state"`
Sort string `json:"sort" form:"sort" default:"desc"`
Pn int64 `json:"pn" form:"pn" default:"1" validate:"gt=0"`
Ps int64 `json:"ps" form:"ps" default:"30" validate:"gt=0"`
}
// ListDirectionItem .
type ListDirectionItem struct {
ID int64 `json:"id"`
NetID int64 `json:"net_id"`
FlowID int64 `json:"flow_id"`
TransitionID int64 `json:"transition_id"`
Direction int8 `json:"direction"`
Order int8 `json:"order"`
Guard string `json:"guard"`
Output string `json:"output"`
UID int64 `json:"uid" gorm:"column:uid"`
DisableTime xtime.Time `json:"disable_time"`
Ctime common.FormatTime `json:"ctime"`
Mtime common.FormatTime `json:"mtime"`
FlowName string `json:"flow_name"`
TransitionName string `json:"transition_name"`
UserName string `json:"user_name"`
NetName string `json:"net_name"`
}
// ListDirectionRes .
type ListDirectionRes struct {
Result []*ListDirectionItem `json:"result"`
Pager Pager `json:"pager"`
}
// SwitchParam .
type SwitchParam struct {
ID int64 `json:"id" form:"id" validate:"required,gt=0"`
Disable bool `json:"disable" form:"disable"`
}
// FlowEditParam .
type FlowEditParam struct {
NetID int64 `form:"net_id" validate:"omitempty,gt=0"`
ID int64 `form:"id" validate:"omitempty,gt=0"`
Name string `form:"name" validate:"required,max=32"`
ChName string `form:"ch_name" validate:"required,max=16"`
Description string `form:"description" validate:"max=60"`
IsStart bool `form:"is_start" default:"false"`
TokenIDList []int64 `form:"token_id_list,split" validate:"omitempty,dive,gt=0"`
}
// TokenBindParam .
type TokenBindParam struct {
ID int64 `json:"id,omitemtpy"`
ChName string `json:"ch_name,omitempty"`
TokenID string `json:"token_id"`
Type int8 `json:"type"`
}
// TransitionEditParam .
type TransitionEditParam struct {
NetID int64 `json:"net_id" validate:"omitempty,gt=0"`
ID int64 `json:"id" validate:"omitempty,gt=0"`
Trigger int8 `json:"trigger" validate:"omitempty,min=1,max=1"`
Limit int64 `json:"limit"`
Name string `json:"name" validate:"required,max=32"`
ChName string `json:"ch_name" validate:"required,max=16"`
Description string `json:"description" validate:"max=60"`
TokenList []*TokenBindParam `json:"token_list" validate:"required,gt=0" `
}
// DirEditParam .
type DirEditParam struct {
ID int64 `form:"id" validate:"omitempty,gt=0"`
NetID int64 `form:"net_id" validate:"omitempty,gt=0"`
FlowID int64 `form:"flow_id" validate:"required,gt=0"`
TransitionID int64 `form:"transition_id" validate:"required,gt=0"`
Direction int8 `form:"direction" validate:"required,min=1,max=2"`
Order int8 `form:"order" validate:"min=0,max=0"`
Output string
Guard string
}
// Pager .
type Pager struct {
Num int64 `json:"num"`
Size int64 `json:"size"`
Total int64 `json:"total"`
}
// ShowFlowResult .
type ShowFlowResult struct {
Flow *Flow `json:"flow"`
Tokens []*TokenBind `json:"tokens"`
IsStart bool `json:"is_start"`
}
// ShowTransitionResult .
type ShowTransitionResult struct {
Transition *Transition `json:"transition"`
Tokens []*TokenBind `json:"tokens"`
}
// ShowDirectionResult .
type ShowDirectionResult struct {
Direction *Direction `json:"direction"`
FlowName string `json:"flow_name"`
TransitionName string `json:"transition_name"`
}
// TokenPackage .
type TokenPackage struct {
Values map[string]interface{} `json:"values"`
TokenIDList []int64 `json:"token_id_list"`
ChName string `json:"ch_name"`
HitAudit bool `json:"hit_audit"`
}
// TriggerResult .
type TriggerResult struct {
RID int64 `json:"rid"`
NetID int64 `json:"net_id"`
SubmitToken *TokenPackage `json:"submit_token"`
ResultToken *TokenPackage `json:"result_token"`
NewFlowID int64 `json:"new_flow_id"`
OldFlowID string `json:"old_flow_id"` //可能有多个旧节点
TransitionID []int64 `json:"transition_id"`
From string `json:"from"`
}
// TranOperation .
type TranOperation struct {
BindIDList string `json:"bind_id_list"`
ChName string `json:"ch_name"`
}
// TranOperationArr .
type TranOperationArr []*TranOperation
func (a TranOperationArr) Len() int {
return len(a)
}
func (a TranOperationArr) Less(i, j int) bool {
return a[i].BindIDList < a[j].BindIDList
}
func (a TranOperationArr) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
// TransitionInfo .
type TransitionInfo struct {
RID int64 `json:"rid"`
FlowID int64 `json:"flow_id"`
Operations []*TranOperation `json:"operations"`
}
// JumpFlowResult .
type JumpFlowResult struct {
RID int64 `json:"rid"`
NetID int64 `json:"net_id"`
SubmitToken *TokenPackage `json:"submit_token"`
ResultToken *TokenPackage `json:"result_token"`
NewFlowID int64 `json:"new_flow_id"`
OldFlowID string `json:"old_flow_id"`
}
// SimpleInfo .
type SimpleInfo struct {
ID int64 `json:"id"`
ChName string `json:"ch_name"`
}
// JumpInfo .
type JumpInfo struct {
Flows []*SimpleInfo `json:"flows"`
Operations []*TranOperation `json:"operations"`
}

View File

@@ -0,0 +1,269 @@
package net
import (
"fmt"
"strconv"
"strings"
"time"
)
//..
const (
TableToken = "net_token"
TableTokenBind = "net_token_bind"
//BindTypeFlow 绑定flow
BindTypeFlow = int8(1)
//BindTypeTransition 绑定单个审核操作
BindTypeTransition = int8(2)
//BindTypeTranBatch 绑定批量审核操作
BindTypeTranBatch = int8(3)
//BindTypeTranHelp 绑定单个非审核操作,提交后不流转
BindTypeTranHelp = int8(4)
//BindTypeTranHelpBatch 绑定批量非审核操作,提交后不流转
BindTypeTranHelpBatch = int8(5)
BindLogTemp = "%s(%d)=%s" //中文名=表达式
BindBatchPrefix = "批量"
BindBatchOptAll = int8(0)
BindBatchOnly = int8(1)
BindBatchNot = int8(2)
)
//TokenCompareAssign 运算符.
const (
TokenCompareAssign = int8(0)
TokenCompareEqual = int8(1)
TokenCompareInequal = int8(2)
TokenCompareGreater = int8(3)
TokenCompareGreaterEqual = int8(4)
TokenCompareLower = int8(5)
TokenCompareLowerEqual = int8(6)
TokenCompareBetween = int8(7)
TokenCompareNotBetween = int8(8)
TokenCompareIn = int8(9)
TokenCompareNotIn = int8(10)
TokenCompareExist = int8(11)
TokenCompareNotExist = int8(12)
//TokenTypeInt8值类型 .
TokenTypeInt8 = int8(0)
TokenTypeInt16 = int8(1)
TokenTypeInt32 = int8(2)
TokenTypeInt64 = int8(3)
TokenTypeString = int8(4)
TokenTypeBool = int8(5)
)
//BindTranType 变迁绑定令牌类型
var BindTranType = []int8{
BindTypeTransition,
BindTypeTranBatch,
BindTypeTranHelp,
BindTypeTranHelpBatch,
}
//BindTypes .
var BindTypes = []int8{
BindTypeFlow,
BindTypeTransition,
BindTypeTranBatch,
BindTypeTranHelp,
BindTypeTranHelpBatch,
}
// TokenCompareDesc .
var TokenCompareDesc = map[int8]string{
TokenCompareAssign: "=",
//TokenCompareEqual: "==",
//TokenCompareInequal: "!=",
//TokenCompareGreater: ">",
//TokenCompareGreaterEqual: ">=",
//TokenCompareLower: "<",
//TokenCompareLowerEqual: "<=",
//TokenCompareBetween: "between", //值有2个数字
//TokenCompareNotBetween: "not between", //值有2个数字
//TokenCompareIn: "in", //a in []
//TokenCompareNotIn: "not in", //a not in []
}
// TokenValueTypeDesc ..
var TokenValueTypeDesc = map[int8]string{
TokenTypeInt8: "int8",
TokenTypeInt16: "int16",
TokenTypeInt32: "int32",
TokenTypeInt64: "int64",
TokenTypeString: "string",
TokenTypeBool: "bool",
}
// Token .
type Token struct {
ID int64 `gorm:"primary_key" json:"id" form:"id" validate:"omitempty,gt=0"`
NetID int64 `gorm:"column:net_id" json:"net_id" form:"net_id" validate:"omitempty,gt=0"`
ChName string `gorm:"column:ch_name" json:"ch_name" form:"ch_name" validate:"required,max=16"`
Name string `gorm:"column:name" json:"name" form:"name" validate:"required,max=10"`
Compare int8 `gorm:"column:compare" json:"compare" form:"compare" validate:"omitempty,min=0,max=10" default:"-1"`
Value string `gorm:"column:value" json:"value" form:"value"`
Type int8 `gorm:"column:type" json:"type" form:"type" default:"-1"`
UID int64 `gorm:"column:uid" json:"uid"`
Ctime time.Time `gorm:"column:ctime" json:"ctime"`
Mtime time.Time `gorm:"column:mtime" json:"mtime"`
}
// TokenBind .
type TokenBind struct {
ID int64 `gorm:"primary_key" json:"id"`
Type int8 `gorm:"column:type" json:"type"`
ElementID int64 `gorm:"column:element_id" json:"element_id"`
TokenID string `gorm:"column:token_id" json:"token_id"`
ChName string `gorm:"column:ch_name" json:"ch_name" `
UID int64 `gorm:"column:uid" json:"uid"`
DisableTime time.Time `gorm:"column:disable_time" json:"disable_time"`
Ctime time.Time `gorm:"column:ctime" json:"ctime"`
Mtime time.Time `gorm:"column:mtime" json:"mtime"`
}
// TokenBindDetail .
type TokenBindDetail struct {
ID int64 `json:"id"`
Type int8 `json:"type"`
ElementID int64 `json:"element_id"`
TokenID string `json:"token_id"`
ChName string `json:"ch_name"`
DisableTime time.Time `json:"disable_time"`
Tokens []*Token `json:"tokens"`
}
// TableName .
func (tk *Token) TableName() string {
return TableToken
}
// IsAssign .
func (tk *Token) IsAssign() bool {
return tk.Compare == TokenCompareAssign
}
// FormatValue .
func (tk *Token) FormatValue() (vt interface{}, err error) {
var (
it int64
ib bool
)
switch tk.Type {
case TokenTypeInt8:
if it, err = strconv.ParseInt(tk.Value, 10, 8); err != nil {
return
}
vt = int8(it)
case TokenTypeInt16:
if it, err = strconv.ParseInt(tk.Value, 10, 16); err != nil {
return
}
vt = int16(it)
case TokenTypeInt32:
if it, err = strconv.ParseInt(tk.Value, 10, 32); err != nil {
return
}
vt = int32(it)
case TokenTypeInt64:
if it, err = strconv.ParseInt(tk.Value, 10, 8); err != nil {
return
}
vt = it
case TokenTypeString:
vt = tk.Value
case TokenTypeBool:
if ib, err = strconv.ParseBool(tk.Value); err != nil {
return
}
vt = ib
default:
err = fmt.Errorf("token not support tp(%d)!", tk.Type)
}
return
}
//FormatLog 日志形式
func (tk *Token) FormatLog() string {
var (
cm, tp string
exist bool
)
if cm, exist = TokenCompareDesc[tk.Compare]; !exist {
cm = strconv.Itoa(int(tk.Compare))
}
if tp, exist = TokenValueTypeDesc[tk.Type]; !exist {
tp = strconv.Itoa(int(tk.Type))
}
return fmt.Sprintf("%s%s%s(%s)", tk.Name, cm, tk.Value, tp)
}
// TableName .
func (tb *TokenBind) TableName() string {
return TableTokenBind
}
// IsAvailable .
func (tb *TokenBind) IsAvailable() bool {
return tb.DisableTime.IsZero()
}
// IsBatch .
func (tb *TokenBind) IsBatch() bool {
return tb.Type == BindTypeTranBatch || tb.Type == BindTypeTranHelpBatch
}
//FormatLog 日志形式
func (tb *TokenBindDetail) FormatLog() string {
var (
logs = []string{}
)
for _, tk := range tb.Tokens {
logs = append(logs, tk.FormatLog())
}
return fmt.Sprintf("{%s: %s}", tb.ChName, strings.Join(logs, ","))
}
// IsAvailable .
func (tb *TokenBindDetail) IsAvailable() bool {
return tb.DisableTime.IsZero()
}
// GetTokenCompare .
func GetTokenCompare(compare int8) string {
v, exist := TokenCompareDesc[compare]
if !exist {
return ""
}
return v
}
// GetTokenValueType .
func GetTokenValueType(tp int8) string {
v, exist := TokenValueTypeDesc[tp]
if !exist {
return ""
}
return v
}
// Int64Slice data.Less and data.Swap
type Int64Slice []int64
func (sl Int64Slice) Len() int {
return len(sl)
}
func (sl Int64Slice) Less(i, j int) bool {
return sl[i] < sl[j]
}
func (sl Int64Slice) Swap(i, j int) {
sl[i], sl[j] = sl[j], sl[i]
}

View File

@@ -0,0 +1,48 @@
package net
import (
"time"
)
//..
const (
TableTransition = "net_transition"
//TriggerManual 人工触发一旦enable执行由人审核提交
TriggerManual = int8(1)
//TriggerAuto 自动触发一旦enable就可执行
TriggerAuto = int8(2)
//TriggerMsg 消息触发一旦enable执行为接收到指定消息
TriggerMsg = int8(3)
)
//TriggerDesc 变迁触发类型描述
var TriggerDesc = map[int8]string{
TriggerAuto: "直序",
TriggerManual: "人工",
TriggerMsg: "消息",
}
//Transition 变迁
type Transition struct {
ID int64 `gorm:"primary_key" json:"id" form:"id" validate:"omitempty,gt=0"`
NetID int64 `gorm:"column:net_id" json:"net_id" form:"net_id" validate:"omitempty,gt=0"`
Trigger int8 `gorm:"column:trigger" json:"trigger" default:"1" form:"trigger"`
Limit int64 `gorm:"column:limit" json:"limit" form:"limit"`
Name string `gorm:"column:name" json:"name" form:"name" validate:"required,max=32"`
ChName string `gorm:"column:ch_name" json:"ch_name" form:"ch_name" validate:"required,max=16"`
Description string `gorm:"column:description" json:"description" form:"description" validate:"max=60"`
UID int64 `gorm:"column:uid" json:"uid"`
DisableTime time.Time `gorm:"column:disable_time" json:"disable_time"`
Ctime time.Time `gorm:"column:ctime" json:"ctime"`
Mtime time.Time `gorm:"column:mtime" json:"mtime"`
}
//TableName .
func (t *Transition) TableName() string {
return TableTransition
}
//IsAvailable .
func (t *Transition) IsAvailable() bool {
return t.DisableTime.IsZero()
}

View File

@@ -0,0 +1,392 @@
package model
import (
"encoding/json"
"fmt"
"strconv"
"time"
"go-common/app/admin/main/aegis/model/common"
modtask "go-common/app/admin/main/aegis/model/task"
"go-common/library/log"
xtime "go-common/library/time"
)
//hash fields
const (
Dispatch = "ds"
Delay = "dy"
Submit = "st_%d_%d" // 参数1:提交状态(任务提交,资源提交,任务关闭) 参数2:提交前属于谁
Release = "rl"
RscState = "rs_%d"
UseTime = "ut"
SetKey = "report_set"
In = "in"
Out = "out"
//type
TypeMeta = int8(0)
TypeTotal = int8(1)
TypeCreate = int8(2) //每日任务增量
TypeDaySubmit = int8(3) //每日任务提交信息
TypeDayUserSubmit = int8(4) //每日审核人员提交信息
)
//TaskReport 任务报表
type TaskReport struct {
ID int64 `json:"id"`
BusinessID int64 `json:"business_id"`
FlowID int64 `json:"flow_id"`
Type int8 `json:"type"`
UID int64 `json:"uid" gorm:"column:uid"`
StatDate time.Time `json:"stat_date"`
Content string `json:"content"`
}
func (t *TaskReport) TableName() string {
return "task_report"
}
//DayPager 按天分页
type DayPager struct {
Pn string `json:"pn"`
IsFirst bool `json:"is_first"` //第一页
IsLast bool `json:"is_last"` //最后一页
}
//ReportSubmitRes .
type ReportSubmitRes struct {
Order []string `json:"order"` //表格列顺序
Header map[string]string `json:"header"` //表格头
Rows [][]map[string]string `json:"rows"` //表格内容体
}
//ReportSubmitItem .
type ReportSubmitItem struct {
StatDate string `json:"stat_date"`
CreateCnt int64 `json:"create_cnt"`
UID int64 `json:"uid"`
Username string `json:"username"`
AvgDur string `json:"avg_dur"`
AvgUtime string `json:"avg_utime"`
FlowID int64 `json:"flow_id"`
SubmitCnt int64 `json:"submit_cnt"`
StateCnt map[string]*ReportSubmitState `json:"state_cnt"`
}
//ReportSubmitState .
type ReportSubmitState struct {
Cnt int64 `json:"cnt"`
Ratio string `json:"ratio"`
}
type ReportSubmitContent struct {
RscStates map[string]int64 `json:"rsc_states"`
AvgDur int64 `json:"avg_dur"`
AvgUtime int64 `json:"avg_utime"`
TotalDur int64 `json:"omitempty,total_dur"`
TotalUtime int64 `json:"omitempty,total_utime"`
}
//OptReport 参数
type OptReport struct {
BizID int64 `form:"business_id" validate:"required"`
FlowID int64 `form:"flow_id"`
UName string `form:"username"`
Bt string `form:"bt"`
Btime time.Time
Et string `form:"et"`
Etime time.Time
Type int8 `form:"type"`
}
//OptReportSubmit 参数
type OptReportSubmit struct {
BizID int64 `form:"business_id" validate:"required"`
FlowID int64 `form:"flow_id"`
Bt string `form:"bt"`
Et string `form:"et"`
Pn string `form:"pn"`
}
//ReportFlowItem 流量
type ReportFlowItem struct {
Hour string `json:"hour"`
In int64 `json:"in"`
Out int64 `json:"out"`
}
//MetaItem .
type MetaItem struct {
DS int64 // 领取
RL int64 // 释放
RP int64 // 通过
ST int64 // 提交
UT int64 // 时长
}
//ReportMeta .
type ReportMeta struct {
Mtime xtime.Time
Content string
UID int64
Type int8
Uname string
}
//Genform 元数据的加工函数,进出审核表格
func Genform(res map[string][]*ReportFlowItem) (form map[string][24]*ReportFlowItem) {
form = make(map[string][24]*ReportFlowItem)
date := func(hour string) (d string, h string) {
d, h = hour[:10], hour[11:]
return
}
emptyflow := func() (res [24]*ReportFlowItem) {
res = [24]*ReportFlowItem{}
for i := 0; i < 24; i++ {
res[i] = &ReportFlowItem{Hour: fmt.Sprintf("%.2d", i)}
}
return res
}
mapcheck := make(map[string]int64) //完全没数据的就不展示了
for uname, arr := range res {
for _, item := range arr {
d, h := date(item.Hour)
hi, _ := strconv.Atoi(h)
key := fmt.Sprintf("%s %s", uname, d)
if arr, ok := form[key]; ok {
arr[hi].In = item.In
arr[hi].Out = item.Out
form[key] = arr
} else {
data := emptyflow()
data[hi].In = item.In
data[hi].Out = item.Out
form[key] = data
}
mapcheck[key] += (item.In + item.Out)
}
}
for k, v := range mapcheck {
if v == 0 {
delete(form, k)
}
}
return
}
//Gentempres 元数据的加工函数,进出审核柱状图1
func Gentempres(opt *OptReport, mnames map[int64]string, metas []*ReportMeta) (tempres map[string]map[int64]*ReportFlowItem) {
var funcin, funcout caculate
if opt.Type == TypeMeta {
funcin = metaIn
funcout = metaOut
} else {
funcin = totalIn
funcout = totalOut
}
tempres = make(map[string]map[int64]*ReportFlowItem)
for _, meta := range metas {
metaM := make(map[string]int64)
if err := json.Unmarshal([]byte(meta.Content), &metaM); err != nil {
log.Error("json.Unmarshal (%s) error(%v)", meta.Content, err)
continue
}
var in, out int64
in += funcin(metaM, meta)
out += funcout(metaM, meta)
hour := meta.Mtime.Time().Format("2006-01-02 15")
item := &ReportFlowItem{
Hour: hour,
In: in,
Out: out,
}
if val, ok := tempres[hour]; ok {
if v, ok := val[meta.UID]; ok {
v.In += in
v.Out += out
tempres[hour][meta.UID] = v
} else {
tempres[hour][meta.UID] = item
}
} else {
tempres[hour] = map[int64]*ReportFlowItem{
meta.UID: item,
}
}
}
return
}
type caculate func(map[string]int64, *ReportMeta) int64
func totalIn(metaM map[string]int64, meta *ReportMeta) (in int64) {
return metaM[In]
}
func totalOut(metaM map[string]int64, meta *ReportMeta) (in int64) {
return metaM[Out]
}
func metaIn(metaM map[string]int64, meta *ReportMeta) (in int64) {
if ds, ok := metaM[Dispatch]; ok { //领取到的
in += ds
}
if rl, ok := metaM[Release]; ok { //释放的
in -= rl
}
return
}
func metaOut(metaM map[string]int64, meta *ReportMeta) (out int64) {
if st, ok := metaM[fmt.Sprintf(Submit, modtask.TaskStateSubmit, meta.UID)]; ok { //本人提交的
out = st
}
return
}
//Genres 元数据的加工函数,进出审核柱状图2
func Genres(opt *OptReport, tempres map[string]map[int64]*ReportFlowItem, mnames map[int64]string) (res map[string][]*ReportFlowItem) {
res = make(map[string][]*ReportFlowItem)
for i := opt.Btime; i.Format("2006-01-02 15") != opt.Etime.Format("2006-01-02 15"); i = i.Add(+1 * time.Hour) {
hour := i.Format("2006-01-02 15")
rt := &ReportFlowItem{
Hour: hour,
}
if val, ok := tempres[hour]; ok {
var tin, tout int64
if opt.Type == TypeMeta {
for uid, uname := range mnames {
if item, ok := val[uid]; ok {
rt = item
tin += item.In
tout += item.Out
} else {
rt.In = 0
rt.Out = 0
}
addtores(res, uname, *rt)
}
} else {
if item, ok := val[0]; ok {
rt = item
tin += item.In
tout += item.Out
}
}
rt.In = tin
rt.Out = tout
addtores(res, "total", *rt)
} else {
addtores(res, "total", *rt)
for _, uname := range mnames {
addtores(res, uname, *rt)
}
}
}
for k, v := range res {
if opt.UName != "" && k != opt.UName {
delete(res, k)
continue
}
var (
insum, outsum = int64(0), int64(0)
)
for _, item := range v {
insum += item.In
outsum += item.Out
}
if insum == 0 && outsum == 0 {
delete(res, k)
}
}
return
}
func addtores(res map[string][]*ReportFlowItem, key string, val ReportFlowItem) {
if total, ok := res[key]; ok {
res[key] = append(total, &val)
} else {
res[key] = []*ReportFlowItem{&val}
}
}
//GenMemberStat 个人24小时统计报表
func GenMemberStat(metas []*ReportMeta, passState int64) (res map[int64][]interface{}, err error) {
tempres := make(map[int64]*MetaItem)
for _, meta := range metas {
metaM := make(map[string]int64)
if err = json.Unmarshal([]byte(meta.Content), &metaM); err != nil {
log.Error("json.Unmarshal (%s) error(%v)", meta.Content, err)
err = nil
continue
}
tmt := &MetaItem{
DS: metaM[Dispatch],
RL: metaM[Release],
RP: metaM[fmt.Sprintf(RscState, passState)],
ST: metaM[fmt.Sprintf(Submit, modtask.TaskStateSubmit, meta.UID)],
UT: metaM[UseTime],
}
if val, ok := tempres[meta.UID]; ok {
val.DS += tmt.DS
val.RL += tmt.RL
val.RP += tmt.RP
val.ST += tmt.ST
val.UT += tmt.UT
} else {
tempres[meta.UID] = tmt
}
}
for uid, v := range tempres {
fmt.Printf("uid:%d v:%+v\n", uid, v)
}
res = make(map[int64][]interface{})
for uid, meta := range tempres {
var (
completerate, passrate, avgtime = "", "", ""
)
total := meta.DS - meta.RL
if total <= 0 {
total = 0
completerate, passrate, avgtime = "0%", "0%", "00:00:00"
} else {
cRate := float32(meta.ST) / float32(total)
pRate := float32(meta.RP) / float32(total)
at := int64(0)
if meta.ST > 0 {
at = meta.UT / meta.ST
}
if cRate < 0.0 || cRate > 1.0 {
completerate = "100%"
} else {
completerate = fmt.Sprintf("%.2f%%", cRate*100)
}
if pRate < 0.0 || pRate > 1.0 {
passrate = "100%"
} else {
passrate = fmt.Sprintf("%.2f%%", pRate*100)
}
if at < 0 {
avgtime = "00:00:00"
} else {
avgtime = common.ParseWaitTime(at)
}
}
res[uid] = []interface{}{total, completerate, passrate, avgtime}
}
return
}

View File

@@ -0,0 +1,41 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = ["resource.go"],
importpath = "go-common/app/admin/main/aegis/model/resource",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/log:go_default_library",
"//library/time:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["resource_test.go"],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = ["//vendor/github.com/smartystreets/goconvey/convey:go_default_library"],
)

View File

@@ -0,0 +1,146 @@
package resource
import (
"encoding/json"
"go-common/library/log"
xtime "go-common/library/time"
)
//Resource .
type Resource struct {
ID int64 `json:"id" gorm:"primary_key" form:"id"`
BusinessID int64 `json:"business_id" gorm:"column:business_id" form:"business_id"`
OID string `json:"oid" gorm:"column:oid" form:"oid"`
MID int64 `json:"mid" gorm:"column:mid" form:"mid"`
Content string `json:"content" gorm:"column:content" form:"content"`
Extra1 int64 `json:"extra1" gorm:"column:extra1" form:"extra1"`
Extra2 int64 `json:"extra2" gorm:"column:extra2" form:"extra2"`
Extra3 int64 `json:"extra3" gorm:"column:extra3" form:"extra3"`
Extra4 int64 `json:"extra4" gorm:"column:extra4" form:"extra4"`
Extra1s string `json:"extra1s" gorm:"column:extra1s" form:"extra1s"`
Extra2s string `json:"extra2s" gorm:"column:extra2s" form:"extra2s"`
MetaData string `json:"metadata" gorm:"column:metadata" form:"metadata"`
Ctime xtime.Time `json:"ctime" gorm:"column:ctime"`
Mtime xtime.Time `json:"mtime" gorm:"column:mtime"`
Extra5 int64 `json:"extra5" gorm:"column:extra5" form:"extra5"`
Extra6 int64 `json:"extra6" gorm:"column:extra6" form:"extra6"`
Extra3s string `json:"extra3s" gorm:"column:extra3s" form:"extra3s"`
Extra4s string `json:"extra4s" gorm:"column:extra4s" form:"extra4s"`
ExtraTime1 string `json:"extratime1" gorm:"column:extratime1" form:"extratime1"`
OCtime string `json:"octime" gorm:"column:octime" form:"octime"`
Ptime string `json:"ptime" gorm:"column:ptime" form:"ptime"`
}
// Result .
type Result struct {
ID int64 `json:"id" gorm:"primary_key" form:"id"`
RID int64 `json:"rid" gorm:"column:rid" form:"rid"`
Attribute int64 `json:"attribute" gorm:"column:attribute" form:"attribute" default:"-1"`
Note string `json:"note" gorm:"column:note" form:"note" submit:"string"`
RejectReason string `json:"reject_reason" gorm:"column:reject_reason" form:"reject_reason" submit:"string"`
ReasonID int64 `json:"reason_id" gorm:"column:reason_id" form:"reason_id" default:"0" submit:"int"`
State int `json:"state" gorm:"column:state" form:"state"`
PubTime xtime.Time `json:"pubtime" gorm:"column:pubtime"`
DelTime xtime.Time `json:"deltime" gorm:"column:deltime"`
Ctime xtime.Time `json:"ctime" gorm:"column:ctime"`
Mtime xtime.Time `json:"mtime" gorm:"column:mtime"`
AttributeList map[string]int8 `json:"attribute_list" gorm:"-" submit:"map"`
}
// AttrParse 属性值解析为属性展开结果
func (r *Result) AttrParse(cfg map[string]uint) {
r.AttributeList = make(map[string]int8)
for name, bit := range cfg {
r.AttributeList[name] = int8((r.Attribute >> bit) & int64(1))
}
}
// AttrSet 展开结果计算回属性值
func (r *Result) AttrSet(cfg map[string]uint) {
var attr int64
for name, bit := range cfg {
if val, ok := r.AttributeList[name]; ok {
attr += int64(val) << bit
}
}
r.Attribute = attr
}
// MetaData 资源扩展数据项目
type MetaData struct {
Name string `json:"name"`
CNDesc string `json:"cndesc"` // 中文描述
Value interface{} `json:"value"`
}
// Res .
type Res struct {
ID int64 `json:"id" gorm:"primary_key" form:"id"`
BusinessID int64 `json:"business_id" gorm:"column:business_id" form:"business_id"`
OID string `json:"oid" gorm:"column:oid" form:"oid"`
MID int64 `json:"mid" gorm:"column:mid" form:"mid"`
Content string `json:"content" gorm:"column:content" form:"content"`
Extra1 int64 `json:"extra1" gorm:"column:extra1" form:"extra1"`
Extra2 int64 `json:"extra2" gorm:"column:extra2" form:"extra2"`
Extra3 int64 `json:"extra3" gorm:"column:extra3" form:"extra3"`
Extra4 int64 `json:"extra4" gorm:"column:extra4" form:"extra4"`
Extra1s string `json:"extra1s,omitempty" gorm:"column:extra1s" form:"extra1s"`
Extra2s string `json:"extra2s,omitempty" gorm:"column:extra2s" form:"extra2s"`
MetaData string `json:"metadata,omitempty" gorm:"column:metadata" form:"metadata"`
Attribute int64 `json:"attribute" gorm:"column:attribute" form:"attribute"`
Note string `json:"note,omitempty" gorm:"column:note" form:"note"`
RejectReason string `json:"reject_reason,omitempty" gorm:"column:reject_reason" form:"reject_reason"`
ReasonID int64 `json:"reason_id,omitempty" gorm:"column:reason_id" form:"reason_id"`
State int64 `json:"state" gorm:"column:state" form:"state"`
Pubtime xtime.Time `json:"pubtime,omitempty" gorm:"column:pubtime"`
Deltime xtime.Time `json:"deltime,omitempty" gorm:"column:deltime"`
Ctime string `json:"ctime"`
Mtime xtime.Time `json:"mtime" gorm:"column:mtime"`
AttributeList map[string]int8 `json:"attribute_list,omitempty"`
Metas map[string]interface{} `json:"metas"`
Extra5 int64 `json:"extra5"`
Extra6 int64 `json:"extra6"`
Extra3s string `json:"extra3s,omitempty"`
Extra4s string `json:"extra4s,omitempty"`
ExtraTime1 string `json:"extratime1,omitempty"`
OCtime string `json:"octime,omitempty"`
Ptime string `json:"ptime,omitempty"`
}
// AttrParse 属性值解析为属性展开结果
func (r *Res) AttrParse(cfg map[string]uint) {
r.AttributeList = make(map[string]int8)
for name, bit := range cfg {
r.AttributeList[name] = int8((r.Attribute >> bit) & int64(1))
}
}
//MetaParse .
func (r *Res) MetaParse() {
if len(r.MetaData) > 0 {
meta := make(map[string]interface{})
if err := json.Unmarshal([]byte(r.MetaData), &meta); err != nil {
log.Error("MetaParse error(%v)", err)
}
r.Metas = meta
}
}
// Args .
type Args struct {
RID int64 `json:"id" form:"rid"`
BusinessID int64 `json:"business_id" form:"business_id"`
OID int64 `json:"oid" form:"oid"`
Changes map[string]interface{} `json:"changes"`
}
// TableName .
func (r *Resource) TableName() string {
return "resource"
}
//TableName .
func (r *Result) TableName() string {
return "resource_result"
}

View File

@@ -0,0 +1,34 @@
package resource
import (
"github.com/smartystreets/goconvey/convey"
"testing"
)
var (
s = &Result{
AttributeList: map[string]int8{"one": 0},
}
ss = &Res{
AttributeList: map[string]int8{"one": 0},
}
)
func TestRes_AttrParse(t *testing.T) {
ss.AttrParse(nil)
}
func TestRes_AttrSet(t *testing.T) {
ss.MetaParse()
}
func TestResult_AttrParse(t *testing.T) {
s.AttrParse(nil)
}
func TestResult_AttrSet(t *testing.T) {
s.AttrSet(map[string]uint{"one": 1})
convey.Convey("Result_AttrSet", t, func() {
convey.So(s.AttributeList["one"], convey.ShouldEqual, 1)
})
}

View File

@@ -0,0 +1,40 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["dot_test.go"],
embed = [":go_default_library"],
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["dot.go"],
importpath = "go-common/app/admin/main/aegis/model/svg",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/aegis/model/net:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,307 @@
package svg
import (
"bytes"
"encoding/json"
"fmt"
"html/template"
"strings"
"go-common/app/admin/main/aegis/model/net"
"go-common/library/log"
)
var tpl = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>流程网描述图</title>
<script src="https://cdn.bootcss.com/viz.js/2.1.1/viz.js"></script>
<script src="https://cdn.bootcss.com/viz.js/2.1.1/full.render.js"></script>
<script>
var json={{.ActionDesc}};
var actions = {{.Actions}};
window.onload = function () {
for( let i =0; i<actions.length; i++){
document.getElementById(actions[i]).onclick = function(e){
var x = e.clientX;
var y = e.clientY;
var content = document.getElementById("content");
var table = '<table bgcolor="LightSteelBlue" border="1">'
var data = JSON.parse(json[actions[i]]);
for (var key in data){
table +='<tr>'
table+='<td>'+key+'</td>'
table+='<td>'+data[key]+'</td>'
table +='</tr>'
}
table += '</table>'
content.innerHTML = table;
content.style.left = x+"px";
content.style.top = y+"px";
content.style.position="absolute";
content.style.display = "block";
content.disabled = true
console.log(content);
}
};
};
</script>
</head>
<body>
<label id="content" background-color="red"></label>
<script>
var viz = new Viz();
viz.renderSVGElement('DotCode')
.then(function(element) {
document.body.appendChild(element);
})
.catch(error => {
// Create a new Viz instance (@see Caveats page for more info)
viz = new Viz();
// Possibly display the error
console.error(error);
});
</script>
</body>
</html>
`
var (
_labelFlow = `%s [label="%s",shape=circle]`
_labelTransition = `%s [label="%s",shape=box,color=lightgrey,style=filled;]`
_labelToken = `%d [label="%s",shape=Mdiamond]`
_labelDirection = `%s->%s`
)
//NetView .
type NetView struct {
*template.Template
Dot *Dot
Data struct {
NetDesc string
DotCode string
Actions []string
ActionDesc map[string]string
}
}
//NewNetView .
func NewNetView() *NetView {
return &NetView{}
}
//SetDot .
func (nv *NetView) SetDot(dot *Dot) {
nv.Dot = dot
nv.Data.DotCode = dot.String()
nv.Data.Actions = append(dot.nodes[:], dot.edges...)
nv.Data.ActionDesc = dot.mapactions
ntpl := strings.Replace(tpl, "DotCode", nv.Data.DotCode, 1)
nv.Template = template.New("流程网概览")
nv.Template, _ = nv.Template.Parse(ntpl)
}
/*
节点用record表示节点绑定的令牌用在同一个record里面
变迁用diamond表示若变迁绑定了令牌则用图包含变迁和令牌
*/
//Dot .
type Dot struct {
*bytes.Buffer
nodes []string
edges []string
mapactions map[string]string
flows map[int64]*net.Flow
trans map[int64]*net.Transition
dirs map[int64]*net.Direction
tokens map[string][]*net.TokenBindDetail
}
//NewDot .
func NewDot() *Dot {
d := &Dot{
mapactions: make(map[string]string),
flows: make(map[int64]*net.Flow),
trans: make(map[int64]*net.Transition),
dirs: make(map[int64]*net.Direction),
tokens: make(map[string][]*net.TokenBindDetail),
}
return d
}
//StartDot .
func (d *Dot) StartDot() *Dot {
d.Buffer = bytes.NewBufferString(`digraph net{rankdir=LR;`)
return d
}
//End .
func (d *Dot) End() string {
d.WriteString("}")
return d.String()
}
//AddTokenBinds .
func (d *Dot) AddTokenBinds(tbs ...*net.TokenBindDetail) *Dot {
for _, tb := range tbs {
key := fmt.Sprintf("%d_%d", tb.Type, tb.ElementID)
if tks, ok := d.tokens[key]; ok {
d.tokens[key] = append(tks, tb)
} else {
d.tokens[key] = []*net.TokenBindDetail{tb}
}
}
return d
}
//AddFlow .
func (d *Dot) AddFlow(flows ...*net.Flow) *Dot {
for _, flow := range flows {
d.flows[flow.ID] = flow
node := fmt.Sprintf(_labelFlow, flow.Name, flow.ChName)
//
nodeid := fmt.Sprintf("node%d", len(d.nodes)+1)
d.nodes = append(d.nodes, nodeid)
bs, _ := json.Marshal(flow)
d.mapactions[nodeid] = string(bs)
//便利token查找绑定
if tks, ok := d.tokens[fmt.Sprintf("1_%d", flow.ID)]; ok {
d.WriteString("subgraph cluster_" + flow.Name + " {")
d.WriteString(node + ";")
for _, tk := range tks {
node := fmt.Sprintf(_labelToken, tk.ID, tk.ChName)
d.WriteString(node + ";")
nodeid := fmt.Sprintf("node%d", len(d.nodes)+1)
d.nodes = append(d.nodes, nodeid)
bs, _ := json.Marshal(tk)
d.mapactions[nodeid] = string(bs)
}
d.WriteString("}")
} else {
d.WriteString(node + ";")
}
}
return d
}
//AddTransitions .
func (d *Dot) AddTransitions(trans ...*net.Transition) *Dot {
for _, tran := range trans {
d.trans[tran.ID] = tran
node := fmt.Sprintf(_labelTransition, tran.Name, tran.ChName)
nodeid := fmt.Sprintf("node%d", len(d.nodes)+1)
d.nodes = append(d.nodes, nodeid)
bs, _ := json.Marshal(tran)
d.mapactions[nodeid] = string(bs)
//便利token查找绑定
if tks, ok := d.tokens[fmt.Sprintf("2_%d", tran.ID)]; ok {
d.WriteString("subgraph cluster_" + tran.Name + " {")
d.WriteString(node + ";")
for _, tk := range tks {
node := fmt.Sprintf(_labelToken, tk.ID, tk.ChName)
d.WriteString(node + ";")
nodeid := fmt.Sprintf("node%d", len(d.nodes)+1)
d.nodes = append(d.nodes, nodeid)
bs, _ := json.Marshal(tk)
d.mapactions[nodeid] = string(bs)
}
d.WriteString("}")
} else {
d.WriteString(node + ";")
}
}
return d
}
//AddDirections .
func (d *Dot) AddDirections(dirs ...*net.Direction) *Dot {
for _, dir := range dirs {
var (
start, end string
flow *net.Flow
trans *net.Transition
)
flow = d.flows[dir.FlowID]
trans = d.trans[dir.TransitionID]
if flow == nil || trans == nil {
log.Error("invalid direction(%+v)", dir)
continue
}
if dir.Direction == 1 {
start, end = flow.Name, trans.Name
}
if dir.Direction == 2 {
start, end = trans.Name, flow.Name
}
edge := fmt.Sprintf(_labelDirection, start, end)
d.WriteString(edge + ";")
edgeid := fmt.Sprintf("edge%d", len(d.edges)+1)
bs, _ := json.Marshal(dir)
d.mapactions[edgeid] = string(bs)
d.edges = append(d.edges, edgeid)
}
return d
}
var (
flow1 = &net.Flow{ID: 1, ChName: "节点1", Name: "flow1"}
flow2 = &net.Flow{ID: 2, ChName: "节点2", Name: "flow2"}
flow3 = &net.Flow{ID: 3, ChName: "节点3", Name: "flow3"}
flow4 = &net.Flow{ID: 4, ChName: "节点4", Name: "flow4"}
flow5 = &net.Flow{ID: 5, ChName: "节点5", Name: "flow5"}
flow6 = &net.Flow{ID: 6, ChName: "节点6", Name: "flow6"}
flow7 = &net.Flow{ID: 7, ChName: "节点7", Name: "flow7"}
tran1 = &net.Transition{ID: 1, ChName: "变迁1", Name: "tran1"}
tran2 = &net.Transition{ID: 2, ChName: "变迁2", Name: "tran2"}
tran3 = &net.Transition{ID: 3, ChName: "变迁3", Name: "tran3"}
dir1 = &net.Direction{ID: 1, FlowID: 1, TransitionID: 1, Direction: 1}
dir2 = &net.Direction{ID: 2, FlowID: 2, TransitionID: 1, Direction: 2}
dir3 = &net.Direction{ID: 3, FlowID: 2, TransitionID: 2, Direction: 1}
dir4 = &net.Direction{ID: 4, FlowID: 2, TransitionID: 3, Direction: 1}
dir5 = &net.Direction{ID: 5, FlowID: 3, TransitionID: 2, Direction: 2}
dir6 = &net.Direction{ID: 6, FlowID: 4, TransitionID: 2, Direction: 2}
dir7 = &net.Direction{ID: 7, FlowID: 5, TransitionID: 3, Direction: 2}
dir8 = &net.Direction{ID: 8, FlowID: 6, TransitionID: 2, Direction: 2}
dir9 = &net.Direction{ID: 9, FlowID: 7, TransitionID: 3, Direction: 2}
tk1 = &net.TokenBindDetail{
ID: 1,
Type: 1,
ElementID: 1,
ChName: "待审核",
}
tk2 = &net.TokenBindDetail{
ID: 2,
Type: 2,
ElementID: 1,
ChName: "通过",
}
)
func DebugSVG() (nv *NetView) {
dot := NewDot()
dot.StartDot().AddTokenBinds(tk1, tk2).
AddFlow(flow1, flow2, flow3, flow4, flow5, flow6, flow7).
AddTransitions(tran1, tran2, tran3).
AddDirections(dir1, dir2, dir3, dir4, dir5, dir6, dir7, dir8, dir9).
End()
nv = NewNetView()
nv.SetDot(dot)
return nv
}

View File

@@ -0,0 +1,23 @@
package svg
import (
"fmt"
"os"
"testing"
)
func Test_dot(t *testing.T) {
dot := NewDot()
dotcode := dot.StartDot().AddTokenBinds(tk1, tk2).
AddFlow(flow1, flow2, flow3, flow4, flow5, flow6, flow7).
AddTransitions(tran1, tran2, tran3).
AddDirections(dir1, dir2, dir3, dir4, dir5, dir6, dir7, dir8, dir9).
End()
nv := NewNetView()
nv.SetDot(dot)
t.Log(nv.Execute(os.Stdout, nv.Data))
fmt.Println(dotcode)
t.Fail()
}

View File

@@ -0,0 +1,35 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"consumer.go",
"task.go",
],
importpath = "go-common/app/admin/main/aegis/model/task",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/aegis/model/common:go_default_library",
"//library/time:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,32 @@
package task
import (
"time"
)
// Role .
type Role struct {
ID int64 `json:"id"`
BID int64 `json:"bid"`
RID int64 `json:"rid"`
Type int8 `json:"type"`
Name string `json:"name"`
}
// WatchItem 审核员状态
type WatchItem struct {
UID int64 `json:"uid"`
Uname string `json:"uname"`
IsOnLine bool `json:"is_online"`
LastOn string `json:"laston"`
LastOff string `json:"lastoff"`
CompleteRate string `json:"complete_rate"`
PassRate string `json:"pass_rate"`
Count int64 `json:"count"`
AvgUT string `json:"avgut"`
BizID int64 `json:"business_id"`
FlowID int64 `json:"flow_id"`
Role int8 `json:"role"`
Mtime time.Time `json:"-"`
State int8 `json:"-"`
}

View File

@@ -0,0 +1,214 @@
package task
import (
"errors"
"context"
"go-common/app/admin/main/aegis/model/common"
libtime "go-common/library/time"
)
//...
const (
ActionConsumerOff = int8(0)
ActionConsumerOn = int8(1)
TaskStateInit = int8(0)
TaskStateDispatch = int8(1)
TaskStateDelay = int8(2)
TaskStateSubmit = int8(3)
TaskStateRscSb = int8(4)
TaskStateClosed = int8(5)
TaskConfigAssign = int8(1)
TaskConfigRangeWeight = int8(2)
TaskConfigEqualWeight = int8(3)
TaskRoleMember = int8(1) //组员
TaskRoleLeader = int8(2) //组长
TaskNoRole = int8(0) //无身份
)
// ErrEmpty empty pool
var (
ErrEmpty = errors.New("empty pool")
ErrRole = errors.New("不在用户组内")
)
// Task ..
type Task struct {
ID int64 `form:"id" json:"id" gorm:"AUTO_INCREMENT;primary_key;"`
BusinessID int64 `form:"business_id" json:"business_id" gorm:"column:business_id"`
FlowID int64 `form:"flow_id" json:"flow_id" gorm:"column:flow_id"`
RID int64 `form:"rid" json:"rid" gorm:"column:rid"`
AdminID int64 `form:"admin_id" json:"admin_id" gorm:"column:admin_id"`
UID int64 `form:"uid" json:"uid" gorm:"column:uid"`
MID int64 `form:"mid" json:"mid" gorm:"column:mid"`
State int8 `form:"state" json:"state" gorm:"column:state"`
Weight int64 `form:"weight" json:"weight" gorm:"column:weight"`
Utime int64 `form:"utime" json:"utime" gorm:"column:utime"`
Gtime common.IntTime `form:"gtime" json:"gtime" gorm:"column:gtime"`
Fans int64 `form:"fans" json:"fans" gorm:"column:fans"`
Group string `form:"group" json:"group" gorm:"column:group"`
Reason string `form:"reason" json:"reason" grom:"column:reason"`
Ctime common.IntTime `form:"ctime" json:"ctime" gorm:"column:ctime"`
Mtime common.IntTime `form:"mtime" json:"mtime" gorm:"column:mtime"`
}
// TableName ...
func (t Task) TableName() string {
return "task"
}
// TempOptions 中间参数
type TempOptions struct {
BisLeader bool // 是否组长
NoCache bool // 不使用缓存
Action string
}
// NextOptions options for Next
type NextOptions struct {
common.BaseOptions
TempOptions
SeizeCount int64 `form:"seize_count" default:"10"` // 抢占多少个
DispatchCount int64 `form:"dispatch_count" default:"1"` // 领取多少个
}
// ListOptions options for List
type ListOptions struct {
common.BaseOptions
common.Pager
TempOptions
BisShow bool // 用于列表展示还是直接派发
State int8 `form:"state"`
}
// SubmitOptions options for Submit
type SubmitOptions struct {
common.BaseOptions
TempOptions
TaskID int64 `form:"task_id"`
Utime uint64
OldUID int64
OldState int8
}
// DelayOptions options for Delay
type DelayOptions struct {
common.BaseOptions
TaskID int64 `form:"task_id"`
Reason string `form:"reason"`
}
// ConfigOption .
type ConfigOption struct {
common.BaseOptions
ID int64 `form:"id"`
Btime string `form:"btime"`
Etime string `form:"etime"`
Description string `form:"description"`
ConfType int8 `form:"conf_type" validate:"required"`
ConfJSON string `form:"conf_json" validate:"required"`
}
// Config .
type Config struct {
ID int64 `form:"id" json:"id" gorm:"AUTO_INCREMENT;primary_key;"`
ConfJSON string `json:"conf_json" gorm:"column:conf_json"`
ConfType int8 `form:"conf_type" json:"conf_type" gorm:"column:conf_type"`
BusinessID int64 `form:"business_id" json:"business_id" gorm:"column:business_id"`
FlowID int64 `form:"flow_id" json:"flow_id" gorm:"column:flow_id"`
Btime libtime.Time `form:"btime" json:"btime" gorm:"column:btime"`
Etime libtime.Time `form:"etime" json:"etime" gorm:"column:etime"`
State int8 `form:"state" json:"state" gorm:"column:state"`
UID int64 `form:"uid" json:"uid" gorm:"column:uid"`
Uname string `form:"uname" json:"uname" gorm:"column:uname"`
Description string `form:"description" json:"description" gorm:"column:description"`
Ctime libtime.Time `form:"ctime" json:"ctime" gorm:"column:ctime"`
Mtime libtime.Time `form:"mtime" json:"mtime" gorm:"column:mtime"`
}
// TableName for orm
func (c Config) TableName() string {
return "task_config"
}
// EqualWeightConfig 等值权重
type EqualWeightConfig struct {
Name string `json:"name"` // taskid 或者 mid
IDs string `json:"ids"`
Weight int64 `json:"weight"`
Type int8 `json:"type"` // 周期或者定值
}
// RangeWeightConfig 权重
type RangeWeightConfig struct {
Name string `json:"name"`
Range []*RangeConfig `json:"range"`
}
// RangeConfig 范围配置
type RangeConfig struct {
Threshold int64 `json:"threshold"`
Weight int64 `json:"weight"`
}
// AssignConfig 指派
type AssignConfig struct {
MIDs []int64 `json:"mids"`
UIDs []int64 `json:"uids"`
}
// QueryParams 配置筛选参数
type QueryParams struct {
common.Pager
ConfType int8 `form:"conf_type"`
State int8 `form:"state"`
BusinessID int64 `form:"business_id"`
FlowID int64 `form:"flow_id"`
Btime string `form:"mtime_from"`
Etime string `form:"mtime_to"`
ConfName string `form:"conf_name"` // 筛选配置具体类型fans,group,waittime,mid,taskid
IDFilter string `form:"id_filter"` // 筛选具体的ID
TypeFilter string `form:"type_filter"` // 筛选动态或静态权重
}
// History 任务日志
type History struct {
TaskID int64 `json:"task_id"`
AdminID int64
UID int64
Reason string
Uname string
Action int8
}
// UnDOStat undo stat
type UnDOStat struct {
Assign int64 `json:"assign_count" gorm:"column:assign"`
Delay int64 `json:"delay_count" gorm:"column:delay"`
Normal int64 `json:"normal_count" gorm:"column:normal"`
}
// Stat 列表页最上方
type Stat struct {
Normal int64 `json:"normal_count" gorm:"column:normal"`
Assign int64 `json:"assign_count" gorm:"column:assign"`
DelayTotal int64 `json:"delay_total" gorm:"column:delayTotal"`
DelayPersonal int64 `json:"delay_personal" gorm:"column:delayPersonal"`
ReviewTotal int64 `json:"review_total"`
ReviewPersonal int64 `json:"review_personal"`
}
// RangeFunc .
type RangeFunc func(context.Context, *ListOptions) (map[int64]*Task, int64, []int64, []int64, error)
// RemoveFunc .
type RemoveFunc func(context.Context, *common.BaseOptions, ...interface{}) error
// ListFuncDB .
type ListFuncDB func(context.Context, map[int64]*Task, []int64, ...interface{}) (map[int64]struct{}, error)