[feat] 重新梳理依赖

This commit is contained in:
what 2024-05-09 13:15:24 +08:00
parent 9172fb2f34
commit bddd754869
28 changed files with 341 additions and 1075 deletions

View File

@ -5,16 +5,16 @@ import (
"strings"
"unicode"
"git.fsdpf.net/go/contracts"
"git.fsdpf.net/go/contracts/res_type"
"git.fsdpf.net/go/db"
"git.fsdpf.net/go/req"
)
type QueryField struct {
ResField
typ contracts.QueryDataType `db:"dataType"`
alias string `db:"alias"`
isExpr bool `db:"isExpr"`
typ req.RouteParamType `db:"dataType"`
alias string `db:"alias"`
isExpr bool `db:"isExpr"`
isOmitempty bool
ignored bool
}
@ -35,20 +35,20 @@ func (this QueryField) IsOmitempty() bool {
return this.isOmitempty
}
func (this QueryField) Type() contracts.QueryDataType {
func (this QueryField) Type() req.RouteParamType {
return this.typ
}
func (this *QueryField) SetOptions(options int) contracts.QueryField {
if options&contracts.QueryField_IsExpr != 0 {
func (this *QueryField) SetOptions(options byte) req.QueryField {
if options&req.IsExpr != 0 {
this.isExpr = true
}
if options&contracts.QueryField_IsOmitempty != 0 {
if options&req.IsOmitempty != 0 {
this.isOmitempty = true
}
if options&contracts.QueryField_Ignored != 0 {
if options&req.Ignored != 0 {
this.ignored = true
}
@ -101,19 +101,19 @@ func (this *QueryField) ToStructField(tags ...string) reflect.StructField {
}
switch this.typ {
case contracts.QueryDataType_String:
case req.ReqString:
typ = reflect.TypeOf(string(""))
case contracts.QueryDataType_Number:
case req.ReqNumber:
typ = reflect.TypeOf(res_type.ResFieldByNumber(0))
case contracts.QueryDataType_Integer:
case req.ReqInteger:
typ = reflect.TypeOf(res_type.ResFieldByInteger(0))
case contracts.QueryDataType_Float:
case req.ReqFloat:
typ = reflect.TypeOf(res_type.ResFieldByFloat(0))
case contracts.QueryDataType_Bool:
case req.ReqBool:
typ = reflect.TypeOf(true)
case contracts.QueryDataType_Array:
case req.ReqArray:
typ = reflect.TypeOf([]any{})
case contracts.QueryDataType_Json:
case req.ReqJson:
typ = reflect.TypeOf(map[string]any{})
}

View File

@ -1,5 +1,7 @@
package base
import "git.fsdpf.net/go/condition"
type ResCondition struct {
Id int `db:"id"`
Pid int `db:"pid"`
@ -36,3 +38,54 @@ type ResWhereExpr struct {
}
type GetResConditions func(categoryUuid string) []ResCondition
// Create Condition By Resource
func NewConditionByRes(items []ResCondition, opts ...condition.Option) (root *condition.Condition) {
conditions := map[int]any{}
for _, item := range items {
switch item.Type {
case "and":
conditions[item.Id] = condition.New()
case "or":
conditions[item.Id] = condition.New(condition.Type(condition.OR))
case "expr":
conditions[item.Id] = condition.NewExpr(
item.ColumnResource, item.Column,
condition.Token(item.Value, condition.TokenType(item.ValueType)),
condition.Operator(condition.ConditionOperator(item.Operator)),
condition.FieldSqlFn(item.ColumnSqlFunc, item.ColumnSqlFuncParam),
condition.IgnoreEmptyParma(item.IgnoreEmptyParma),
)
}
if item.Pid == 0 && (item.Type == "and" || item.Type == "or") {
root = conditions[item.Id].(*condition.Condition)
}
}
for _, item := range items {
parent := root
if item.Pid == 0 {
continue
} else {
parent = conditions[item.Pid].(*condition.Condition)
}
switch item.Type {
case "and", "or":
parent.SetCondition(conditions[item.Id].(*condition.Condition))
case "expr":
parent.SetExpr(conditions[item.Id].(*condition.ConditionExpr))
}
}
if root == nil {
root = condition.New()
}
root.SetOption(opts...)
return root
}

View File

@ -7,24 +7,24 @@ import (
"strconv"
"strings"
"git.fsdpf.net/go/contracts"
"git.fsdpf.net/go/contracts/res_type"
"git.fsdpf.net/go/db"
"git.fsdpf.net/go/db/schema"
"git.fsdpf.net/go/req"
"github.com/google/uuid"
"github.com/spf13/cast"
)
// 资源字段
type ResField struct {
Uuid string `db:"uuid"`
Name string `db:"name"`
Code string `db:"code"`
CodeResource string `db:"codeResource"`
DataType contracts.ResDataType `db:"table_type"`
Length string `db:"length"`
Comment string `db:"comment"`
Default string `db:"default"`
Uuid string `db:"uuid"`
Name string `db:"name"`
Code string `db:"code"`
CodeResource string `db:"codeResource"`
DataType req.ResDataType `db:"table_type"`
Length string `db:"length"`
Comment string `db:"comment"`
Default string `db:"default"`
}
func (this ResField) ToStructField(tags ...string) reflect.StructField {
@ -38,16 +38,16 @@ func (this ResField) ToStructField(tags ...string) reflect.StructField {
}
switch this.DataType {
case contracts.ResDataType_String, contracts.ResDataType_Text, contracts.ResDataType_Enum,
contracts.ResDataType_Timestamp, contracts.ResDataType_Date, contracts.ResDataType_Datetime:
case req.ResString, req.ResText, req.ResEnum,
req.ResTimestamp, req.ResDate, req.ResDatetime:
typ = reflect.TypeOf(string(""))
case contracts.ResDataType_Integer, contracts.ResDataType_SmallInteger:
case req.ResInteger, req.ResSmallInteger:
typ = reflect.TypeOf(res_type.ResFieldByInteger(0))
case contracts.ResDataType_Decimal:
case req.ResDecimal:
typ = reflect.TypeOf(float64(0))
case contracts.ResDataType_Boolean:
case req.ResBoolean:
typ = reflect.TypeOf(true)
case contracts.ResDataType_Json:
case req.ResJson:
if this.Default != "" && this.Default[0:1] == "[" {
typ = reflect.TypeOf([]any{})
} else {
@ -74,47 +74,47 @@ func (this ResField) GetName() string {
return this.Name
}
func (this ResField) GetDataType() contracts.ResDataType {
func (this ResField) GetDataType() req.ResDataType {
return this.DataType
}
func (this ResField) GetQueryDataType() contracts.QueryDataType {
func (this ResField) GetQueryDataType() req.RouteParamType {
switch this.GetDataType() {
case contracts.ResDataType_Enum,
contracts.ResDataType_Timestamp, contracts.ResDataType_Date,
contracts.ResDataType_Datetime, contracts.ResDataType_String,
contracts.ResDataType_Text:
return contracts.QueryDataType_String
case contracts.ResDataType_Integer, contracts.ResDataType_SmallInteger:
return contracts.QueryDataType_Integer
case contracts.ResDataType_Decimal:
return contracts.QueryDataType_Float
case contracts.ResDataType_Boolean:
return contracts.QueryDataType_Bool
case contracts.ResDataType_Json:
case req.ResEnum,
req.ResTimestamp, req.ResDate,
req.ResDatetime, req.ResString,
req.ResText:
return req.ReqString
case req.ResInteger, req.ResSmallInteger:
return req.ReqInteger
case req.ResDecimal:
return req.ReqFloat
case req.ResBoolean:
return req.ReqBool
case req.ResJson:
if this.Default != "" && this.Default[0:1] == "[" {
return contracts.QueryDataType_Array
return req.ReqArray
}
return contracts.QueryDataType_Json
return req.ReqJson
}
return contracts.QueryDataType_String
return req.ReqString
}
func (this ResField) ToValue(v any) any {
switch this.DataType {
case contracts.ResDataType_String, contracts.ResDataType_Text, contracts.ResDataType_Enum,
contracts.ResDataType_Timestamp, contracts.ResDataType_Date, contracts.ResDataType_Datetime:
case req.ResString, req.ResText, req.ResEnum,
req.ResTimestamp, req.ResDate, req.ResDatetime:
return strings.Trim(cast.ToString(v), " ")
case contracts.ResDataType_Integer, contracts.ResDataType_SmallInteger:
case req.ResInteger, req.ResSmallInteger:
return cast.ToInt(v)
case contracts.ResDataType_Decimal:
case req.ResDecimal:
return strings.Trim(cast.ToString(v), " ")
case contracts.ResDataType_Boolean:
case req.ResBoolean:
if v, _ := strconv.ParseBool(fmt.Sprintf("%v", v)); v {
return 1
}
return 0
case contracts.ResDataType_Json:
case req.ResJson:
if v == nil {
if this.Default != "" && this.Default[0:1] == "[" {
return db.Raw("'[]'")
@ -142,7 +142,7 @@ func (this ResField) ToValue(v any) any {
}
func (this ResField) GetRawDefault(driver string) db.Expression {
if this.DataType == contracts.ResDataType_Json {
if this.DataType == req.ResJson {
if this.Default != "" && this.Default[0:1] == "[" {
return db.Raw("'[]'")
} else if this.Default != "" && this.Default[0:1] == "{" {
@ -150,7 +150,7 @@ func (this ResField) GetRawDefault(driver string) db.Expression {
} else if this.Default == "" {
return db.Raw("'{}'")
}
} else if this.DataType == contracts.ResDataType_Boolean {
} else if this.DataType == req.ResBoolean {
if v, _ := strconv.ParseBool(this.Default); v {
return db.Raw("'1'")
}
@ -169,7 +169,7 @@ func (this ResField) GetRawDefault(driver string) db.Expression {
}
if this.Default == "" {
if this.GetDataType() == contracts.ResDataType_Date || this.GetDataType() == contracts.ResDataType_Datetime {
if this.GetDataType() == req.ResDate || this.GetDataType() == req.ResDatetime {
return db.Raw("NULL")
}
return db.Raw("''")
@ -255,7 +255,7 @@ func (this ResField) ToBlueprint(table *schema.Blueprint) (temp *schema.ColumnDe
return temp
}
func (this ResField) ToQueryField(t contracts.QueryDataType, alias string, options int) contracts.QueryField {
func (this ResField) ToQueryField(t req.RouteParamType, alias string, options byte) req.QueryField {
o := &QueryField{
ResField: this,
typ: t,

View File

@ -2,6 +2,7 @@ package base
import (
"git.fsdpf.net/go/contracts"
"git.fsdpf.net/go/req"
)
type ResRelation struct {
@ -23,7 +24,7 @@ type GetResRelations func(categoryUuid string) []ResRelation
type GetOrmJoinsByResRelations func(root string, items []ResRelation) []contracts.Join
// 获取被关联对象的资源
type GetResRelationResource func(r ResRelation) (contracts.Resource, bool)
type GetResRelationResource func(r ResRelation) (req.Resource, bool)
// 资源关联依赖
func GetJoinResDependencies(root string, items []ResRelation) (dependencies []string) {

View File

@ -11,8 +11,8 @@ import (
"github.com/samber/lo"
"git.fsdpf.net/go/contracts"
"git.fsdpf.net/go/contracts/support"
"git.fsdpf.net/go/db"
"git.fsdpf.net/go/req"
)
// 资源变更事件
@ -29,7 +29,7 @@ type ResChangeEventTopicPayload struct {
type ResChangeRecordTopicPayload struct {
Type string // insert | delete | update
User contracts.User // 操作用户
User req.User // 操作用户
Res Resource // 变更资源
Result sql.Result // 执行结果
Old []map[string]any // 旧数据
@ -92,7 +92,7 @@ func (this Resource) IsSystem() bool {
}
// 资源字段
func (this Resource) GetFields() (result []contracts.ResField) {
func (this Resource) GetFields() (result []req.ResField) {
for _, item := range this.Fields {
result = append(result, item)
}
@ -100,15 +100,15 @@ func (this Resource) GetFields() (result []contracts.ResField) {
}
// 资源字段
func (this Resource) GetField(code string) (contracts.ResField, bool) {
return lo.Find(this.GetFields(), func(v contracts.ResField) bool {
func (this Resource) GetField(code string) (req.ResField, bool) {
return lo.Find(this.GetFields(), func(v req.ResField) bool {
return v.GetCode() == code
})
}
// 判断资源字段
func (this Resource) HasField(code string) bool {
return lo.SomeBy(this.GetFields(), func(v contracts.ResField) bool {
return lo.SomeBy(this.GetFields(), func(v req.ResField) bool {
return v.GetCode() == code
})
}
@ -147,7 +147,7 @@ func (this Resource) GetDBDriver() string {
return this.GetDBConn().GetConfig().Driver
}
func (this Resource) GetAuthDBTable(u contracts.User, params ...any) *db.Builder {
func (this Resource) GetAuthDBTable(u req.User, params ...any) *db.Builder {
builder := this.GetDBTable(append(params, u)...)
// 数据权限过滤
@ -164,7 +164,7 @@ func (this Resource) GetAuthDBTable(u contracts.User, params ...any) *db.Builder
func (this Resource) GetDBTable(params ...any) *db.Builder {
builder := this.GetDBBuilder()
var user contracts.User
var user req.User
alias := this.Code
for _, param := range params {
@ -173,7 +173,7 @@ func (this Resource) GetDBTable(params ...any) *db.Builder {
builder.Tx = v
case string:
alias = v
case contracts.User:
case req.User:
user = v
}
}
@ -213,7 +213,7 @@ func (this Resource) GetDBTable(params ...any) *db.Builder {
return builder.Table(string(this.GetTable()), alias)
}
func (this Resource) WithRolesCondition(b *db.Builder, t string, u contracts.User) error {
func (this Resource) WithRolesCondition(b *db.Builder, t string, u req.User) error {
isFullRight := false
isFullNot := false
@ -268,7 +268,7 @@ func (this Resource) WithRolesCondition(b *db.Builder, t string, u contracts.Use
return db.ToSql()
} else if conditions.IsNotEmpty() {
oOrm := NewOrm(this, nil)
oOrm.SetGlobalParams(support.NewGlobalParam("{}", u))
oOrm.SetGlobalParams(req.NewGlobalParam("{}", u))
db.Where(conditions.ToSql(oOrm.GetModel()))
@ -322,7 +322,7 @@ func (this Resource) formatSaveValue(data map[string]any) {
}
// 填充保存数据
func (this Resource) fillSaveValue(data map[string]any, u contracts.User, t string) {
func (this Resource) fillSaveValue(data map[string]any, u req.User, t string) {
for _, field := range this.GetFields() {
fCode := field.GetCode()
@ -401,7 +401,7 @@ func (this Resource) onResEvent(builder *db.Builder) {
}
// 用户事件
func (this Resource) onUserEvent(builder *db.Builder, user contracts.User) {
func (this Resource) onUserEvent(builder *db.Builder, user req.User) {
old := []map[string]any{}
builder.Before(func(b *db.Builder, t string, data ...map[string]any) {
@ -439,7 +439,7 @@ func (this Resource) onUserEvent(builder *db.Builder, user contracts.User) {
})
}
func NewVirtualResource(pRes Resource, code, name, sql string, fields []ResField) contracts.Resource {
func NewVirtualResource(pRes Resource, code, name, sql string, fields []ResField) req.Resource {
return &Resource{
Uuid: code,
PUuid: pRes.Uuid,

View File

@ -3,7 +3,7 @@ package base
import (
"github.com/samber/lo"
"git.fsdpf.net/go/contracts"
"git.fsdpf.net/go/req"
)
type user struct {
@ -12,7 +12,7 @@ type user struct {
username string
nickname string
roles []string
runtime contracts.UserRuntime
runtime req.UserRuntime
}
func (this user) ID() int64 {
@ -47,19 +47,19 @@ func (this user) IsAnonymous() bool {
return this.id == 0
}
func (this user) Runtime() contracts.UserRuntime {
func (this user) Runtime() req.UserRuntime {
return this.runtime
}
// 获取匿名用户
func GetAnonymous(opts ...contracts.UserRuntimeOption) contracts.User {
func GetAnonymous(opts ...req.UserRuntimeOption) req.User {
u := user{
id: 0,
uuid: "00000000-0000-0000-0000-000000000000",
username: "anonymous",
nickname: "匿名者",
roles: []string{"00000000-0000-0000-0000-000000000000"},
runtime: contracts.UserRuntime{},
runtime: req.UserRuntime{},
}
for _, opt := range opts {
@ -70,14 +70,14 @@ func GetAnonymous(opts ...contracts.UserRuntimeOption) contracts.User {
}
// 系统用户
func GetSystemUser(opts ...contracts.UserRuntimeOption) contracts.User {
func GetSystemUser(opts ...req.UserRuntimeOption) req.User {
u := user{
id: -1,
uuid: "ffffffff-ffff-ffff-ffff-ffffffffffff",
username: "system",
nickname: "系统",
roles: []string{"ffffffff-ffff-ffff-ffff-ffffffffffff"},
runtime: contracts.UserRuntime{},
runtime: req.UserRuntime{},
}
for _, opt := range opts {

View File

@ -1,7 +1,9 @@
package contracts
import "git.fsdpf.net/go/req"
type Captcha interface {
RouteMiddleware
req.RouteMiddleware
Verify(answer string, clear bool) error
Generate(captchaUuid, recipient, ip string, u User) (body string, id int64, err error)
Generate(captchaUuid, recipient, ip string, u req.User) (body string, id int64, err error)
}

View File

@ -1,6 +1,7 @@
package contracts
import (
"git.fsdpf.net/go/req"
"github.com/samber/do"
)
@ -10,7 +11,7 @@ type Controller interface {
// 获取 Container
Container() *do.Injector
// 派遣一个任务
Dispatch(job string, payload any, u User) error
Dispatch(job string, payload any, u req.User) error
}
type BaseController struct {
@ -25,7 +26,7 @@ func (BaseController) Init() error {
return nil
}
func (this BaseController) Dispatch(job string, payload any, u User) error {
func (this BaseController) Dispatch(job string, payload any, u req.User) error {
return do.MustInvoke[JobService](this.Container()).Dispatch(job, payload, u)
}

View File

@ -1,5 +1,7 @@
package contracts
import "git.fsdpf.net/go/req"
type CronService interface {
Start() error
Stop() error
@ -9,13 +11,13 @@ type CronService interface {
type Cron interface {
Controller
// 任务处理
Run(User) error
Run(req.User) error
}
type CronBase struct {
Controller
}
func (CronBase) Run(User) error {
func (CronBase) Run(req.User) error {
return nil
}

View File

@ -1,55 +0,0 @@
package contracts
import (
"time"
)
type GlobalParams interface {
User() User
// 获取路径内容
Get(p string) GlobalParams
// 路径包裹
Wrapped(p string) GlobalParams
// 追加到新 json
AppendTo(root, p string) GlobalParams
// 通过路径设置参数
Set(p string, v any) bool
// 通过路径设置原始参数
SetRaw(p string, v string) bool
// 删除路径参数
Delete(p string) bool
// 获取原始JOSN字符串
Raw() string
// 转数组 GlobalParams
Array() []GlobalParams
// 判断内容是否存在
Exists() bool
Value() any
Bool() bool
Time() time.Time
TimeInDefaultLocation(l *time.Location) time.Time
Float64() float64
Float32() float32
Int64() int64
Int32() int32
Int16() int16
Int8() int8
Int() int
Uint() uint
Uint64() uint64
Uint32() uint32
Uint16() uint16
Uint8() uint8
String() string
StringMapString() map[string]string
StringMapStringSlice() map[string][]string
StringMapBool() map[string]bool
StringMapInt() map[string]int
StringMapInt64() map[string]int64
StringMap() map[string]any
Slice() []any
BoolSlice() []bool
StringSlice() []string
IntSlice() []int
}

13
go.mod
View File

@ -3,23 +3,26 @@ module git.fsdpf.net/go/contracts
go 1.21
require (
git.fsdpf.net/go/db v0.0.0-20230621051209-5740d112407f
github.com/go-chi/chi/v5 v5.0.10
git.fsdpf.net/go/condition v0.0.0-20240509034445-afc243ea916e
git.fsdpf.net/go/db v0.0.0-20230731125324-11651ea6640b
github.com/go-chi/chi/v5 v5.0.12
github.com/golang/protobuf v1.5.2
github.com/google/uuid v1.3.0
github.com/gorilla/websocket v1.5.0
github.com/jhump/protoreflect v1.15.1
github.com/lestrrat-go/jwx v1.2.25
github.com/samber/do v1.6.0
github.com/samber/lo v1.38.1
github.com/spf13/cast v1.5.0
github.com/samber/lo v1.39.0
github.com/spf13/cast v1.6.0
github.com/spf13/viper v1.15.0
github.com/tidwall/gjson v1.14.4
github.com/tidwall/gjson v1.17.1
github.com/tidwall/sjson v1.2.5
google.golang.org/grpc v1.52.0
)
require (
git.fsdpf.net/go/req v0.0.0-20240509034400-4ef8c130a758 // indirect
git.fsdpf.net/go/utils v0.0.0-20240509025914-c03a9cb48aff // indirect
github.com/bufbuild/protocompile v0.4.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect

34
go.sum
View File

@ -36,8 +36,34 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
git.fsdpf.net/go/condition v0.0.0-20240509022115-37018837d1b0 h1:MHjkN+zrSCqb7Qswn9fFrHT4XaoDnGbXz0ssSKnWnQk=
git.fsdpf.net/go/condition v0.0.0-20240509022115-37018837d1b0/go.mod h1:Zj9yrMa/A3WICTc9zn3W55ociuoBompEsVPo6EUXW5Q=
git.fsdpf.net/go/condition v0.0.0-20240509023514-a871ccfa75ac h1:pJQ0sFjPtv/RCy8k0mC/Kpn/j6As5bSqXyG0MWaylhc=
git.fsdpf.net/go/condition v0.0.0-20240509023514-a871ccfa75ac/go.mod h1:Zj9yrMa/A3WICTc9zn3W55ociuoBompEsVPo6EUXW5Q=
git.fsdpf.net/go/condition v0.0.0-20240509024751-9694d9033266 h1:s5On5PKF1ZiIGgq6R2Nk/2GcURuZxDAVK1Sru54Ybn0=
git.fsdpf.net/go/condition v0.0.0-20240509024751-9694d9033266/go.mod h1:Zj9yrMa/A3WICTc9zn3W55ociuoBompEsVPo6EUXW5Q=
git.fsdpf.net/go/condition v0.0.0-20240509030058-b0e337133e44 h1:XHJxWJuofEL7TLMDBsywi48nciaon8bEFOJLMYkOrNk=
git.fsdpf.net/go/condition v0.0.0-20240509030058-b0e337133e44/go.mod h1:xgX0fc3LEgrPk9tihGQqoQND4EWlNgYbLCi70TuCvvM=
git.fsdpf.net/go/condition v0.0.0-20240509034445-afc243ea916e h1:ZfwjqZS5URF4Y0JfQeytSdmXimJ4l74ooWRppza+3Tk=
git.fsdpf.net/go/condition v0.0.0-20240509034445-afc243ea916e/go.mod h1:K5ocyKVxgC5mI1k/crgrEozK0r51qAavWg0hweXo6PU=
git.fsdpf.net/go/db v0.0.0-20230621051209-5740d112407f h1:H+/H6j+hyFMgSy+tUNmymRy7/PWQRjjp8qY/DrhwrsY=
git.fsdpf.net/go/db v0.0.0-20230621051209-5740d112407f/go.mod h1:397Sdx1cJS0OlHtTX1bVl//9k3Xn0Klnc6jC4MAkb6w=
git.fsdpf.net/go/db v0.0.0-20230731125324-11651ea6640b h1:fRgWNOQ9dAYuUZHQ24oi1XqRbJIcJvZGbnQDaAKI7IY=
git.fsdpf.net/go/db v0.0.0-20230731125324-11651ea6640b/go.mod h1:397Sdx1cJS0OlHtTX1bVl//9k3Xn0Klnc6jC4MAkb6w=
git.fsdpf.net/go/req v0.0.0-20240508133526-672fc634ef20 h1:PhjRtac2r0Vn1WBBzhRhz4//bJhHgkf/SHZe3mQYPto=
git.fsdpf.net/go/req v0.0.0-20240508133526-672fc634ef20/go.mod h1:S+p7t3XclKxsvaXQng7AMmqEGq11FSnMzxOtv1z8JUw=
git.fsdpf.net/go/req v0.0.0-20240509031332-f00b993f9c7d h1:TKNhQWDKyL50eVC/ptur1YuRkjRnKOlMsE1Y9tFCVbk=
git.fsdpf.net/go/req v0.0.0-20240509031332-f00b993f9c7d/go.mod h1:S+p7t3XclKxsvaXQng7AMmqEGq11FSnMzxOtv1z8JUw=
git.fsdpf.net/go/req v0.0.0-20240509031626-6501b5ed0f2b h1:KlVBAuWnFt1lcRTCcBU165MIldJqleO/LahWrd3FvUA=
git.fsdpf.net/go/req v0.0.0-20240509031626-6501b5ed0f2b/go.mod h1:S+p7t3XclKxsvaXQng7AMmqEGq11FSnMzxOtv1z8JUw=
git.fsdpf.net/go/req v0.0.0-20240509033523-c8cda2d8db56 h1:7ElgXUzt75brzOr44mItipTQTk++kZNoGOyTWHLxkTU=
git.fsdpf.net/go/req v0.0.0-20240509033523-c8cda2d8db56/go.mod h1:S+p7t3XclKxsvaXQng7AMmqEGq11FSnMzxOtv1z8JUw=
git.fsdpf.net/go/req v0.0.0-20240509033936-f8a11598db60 h1:hHrEcUSbtajC2LAo2fvEo7yrSSDeM/s5FAuQluP7yZQ=
git.fsdpf.net/go/req v0.0.0-20240509033936-f8a11598db60/go.mod h1:S+p7t3XclKxsvaXQng7AMmqEGq11FSnMzxOtv1z8JUw=
git.fsdpf.net/go/req v0.0.0-20240509034400-4ef8c130a758 h1:nHys8Bwb29b/FvnE100KVH62aD2j5CEPxTQ/RRHo27k=
git.fsdpf.net/go/req v0.0.0-20240509034400-4ef8c130a758/go.mod h1:S+p7t3XclKxsvaXQng7AMmqEGq11FSnMzxOtv1z8JUw=
git.fsdpf.net/go/utils v0.0.0-20240509025914-c03a9cb48aff h1:1hokQGKGIstoI7WDBir2N24OGgnussZ3GmucK4TQRuI=
git.fsdpf.net/go/utils v0.0.0-20240509025914-c03a9cb48aff/go.mod h1:NUoyQtFr905YT+pi850mvSf4YX0WghQIcMQkTvize5o=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
@ -67,6 +93,8 @@ github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -186,10 +214,14 @@ github.com/samber/do v1.6.0 h1:Jy/N++BXINDB6lAx5wBlbpHlUdl0FKpLWgGEV9YWqaU=
github.com/samber/do v1.6.0/go.mod h1:DWqBvumy8dyb2vEnYZE7D7zaVEB64J45B0NjTlY/M4k=
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA=
github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@ -213,6 +245,8 @@ github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNG
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=

41
http.go
View File

@ -3,6 +3,7 @@ package contracts
import (
"net/http"
"git.fsdpf.net/go/req"
"github.com/samber/do"
)
@ -19,36 +20,36 @@ type HttpController interface {
Controller
// 获取用户信息
User() User
User() req.User
// 获取请求信息
Request() *http.Request
// 请求处理
Execute(GlobalParams) any
Execute(req.GlobalParams) any
// 路由信息
Route() Route
Route() req.Route
// 内部调用
Call(code string, params map[string]any, category ...RouteCategory) (HttpResponse, error)
Call(code string, params map[string]any, category ...req.RouteCategory) (req.HttpResponse, error)
// 内部调用
// Invoke()
// 数据库权限
AuthDB() ResAuthDB
AuthDB() req.ResAuthDB
}
type WsController interface {
HttpController
// 请求处理
ExecuteWS(GlobalParams) error
ExecuteWS(req.GlobalParams) error
// 获取 Ws 客户端
WsClient() WsClient
// 获取 Ws 标识
WsClientId(GlobalParams) WsClientID
WsClientId(req.GlobalParams) WsClientID
// 获取 Ws 分组
WsClientGroup(GlobalParams) WsClientGroup
WsClientGroup(req.GlobalParams) WsClientGroup
}
type HttpHandleController struct {
@ -65,27 +66,27 @@ func (this HttpHandleController) Request() *http.Request {
return this.request
}
func (this HttpHandleController) Route() Route {
return this.Request().Context().Value(RouteCtx{Name: "Route"}).(Route)
func (this HttpHandleController) Route() req.Route {
return this.Request().Context().Value(req.RouteCtx{Name: "Route"}).(req.Route)
}
func (this HttpHandleController) User() User {
return this.Request().Context().Value(RouteCtx{Name: "User"}).(User)
func (this HttpHandleController) User() req.User {
return this.Request().Context().Value(req.RouteCtx{Name: "User"}).(req.User)
}
func (this HttpHandleController) Call(code string, params map[string]any, category ...RouteCategory) (HttpResponse, error) {
return do.MustInvoke[Router](this.Container()).Call(this.Request(), code, params, category...)
func (this HttpHandleController) Call(code string, params map[string]any, category ...req.RouteCategory) (req.HttpResponse, error) {
return do.MustInvoke[req.Router](this.Container()).Call(this.Request(), code, params, category...)
}
func (HttpHandleController) Execute(params GlobalParams) any {
func (HttpHandleController) Execute(params req.GlobalParams) any {
return nil
}
func (HttpHandleController) AuthDB() ResAuthDB {
return ResAuthOn
func (HttpHandleController) AuthDB() req.ResAuthDB {
return req.ResAuthOn
}
func (WsHandleController) ExecuteWS(params GlobalParams) error {
func (WsHandleController) ExecuteWS(params req.GlobalParams) error {
return nil
}
@ -93,12 +94,12 @@ func (this WsHandleController) WsClient() WsClient {
return this.ws
}
func (WsHandleController) WsClientId(GlobalParams) WsClientID {
func (WsHandleController) WsClientId(req.GlobalParams) WsClientID {
wsClientID++
return wsClientID
}
func (WsHandleController) WsClientGroup(GlobalParams) WsClientGroup {
func (WsHandleController) WsClientGroup(req.GlobalParams) WsClientGroup {
return defaultWsClientGroup
}

8
job.go
View File

@ -1,22 +1,24 @@
package contracts
import "git.fsdpf.net/go/req"
type JobService interface {
Start() error
Stop() error
Restart() error
Dispatch(job string, payload any, u User) error
Dispatch(job string, payload any, u req.User) error
}
type Job interface {
Controller
// 任务处理
Handle(any, User) error
Handle(any, req.User) error
}
type JobBase struct {
Controller
}
func (JobBase) Handle(any, User) error {
func (JobBase) Handle(any, req.User) error {
return nil
}

21
mqtt.go
View File

@ -1,6 +1,7 @@
package contracts
import (
"git.fsdpf.net/go/req"
"github.com/samber/do"
)
@ -36,15 +37,15 @@ type Mqtt interface {
// 断开链接
// OnDisconnect(g GlobalParams, topic string) error
// 订阅事件
OnSubscribed(g GlobalParams, topic string) error
OnSubscribed(g req.GlobalParams, topic string) error
// 取消订阅事件
OnUnsubscribed(g GlobalParams, topic string) error
OnUnsubscribed(g req.GlobalParams, topic string) error
// 消息发布事件
OnMessage(g GlobalParams, topic string, retain bool, qos byte) error
OnMessage(g req.GlobalParams, topic string, retain bool, qos byte) error
// 消息被丢弃
OnMessageDropped(g GlobalParams, topic string, retain bool, qos byte) error
OnMessageDropped(g req.GlobalParams, topic string, retain bool, qos byte) error
// 原生消息修改
OnPublish(g GlobalParams, topic string, retain bool, qos byte, raw []byte) ([]byte, error)
OnPublish(g req.GlobalParams, topic string, retain bool, qos byte, raw []byte) ([]byte, error)
// 保留类型消息事件
// OnRetainMessage(g GlobalParams, topic string) error
// Qos消息完成事件
@ -59,23 +60,23 @@ type MqttHandle struct {
Controller
}
func (this *MqttHandle) OnSubscribed(g GlobalParams, topic string) error {
func (this *MqttHandle) OnSubscribed(g req.GlobalParams, topic string) error {
return ErrFuncNotImplemented
}
func (this MqttHandle) OnUnsubscribed(g GlobalParams, topic string) error {
func (this MqttHandle) OnUnsubscribed(g req.GlobalParams, topic string) error {
return ErrFuncNotImplemented
}
func (this MqttHandle) OnMessage(g GlobalParams, topic string, retain bool, qos byte) error {
func (this MqttHandle) OnMessage(g req.GlobalParams, topic string, retain bool, qos byte) error {
return ErrFuncNotImplemented
}
func (this MqttHandle) OnMessageDropped(g GlobalParams, topic string, retain bool, qos byte) error {
func (this MqttHandle) OnMessageDropped(g req.GlobalParams, topic string, retain bool, qos byte) error {
return ErrFuncNotImplemented
}
func (this MqttHandle) OnPublish(g GlobalParams, topic string, retain bool, qos byte, raw []byte) ([]byte, error) {
func (this MqttHandle) OnPublish(g req.GlobalParams, topic string, retain bool, qos byte, raw []byte) ([]byte, error) {
return nil, ErrFuncNotImplemented
}

104
orm.go
View File

@ -3,7 +3,9 @@ package contracts
import (
"reflect"
"git.fsdpf.net/go/condition"
"git.fsdpf.net/go/db"
"git.fsdpf.net/go/req"
)
type OrmExecute int
@ -30,47 +32,18 @@ const (
RelationType_Right RelationType = "right"
)
const (
ConditionType_OR ConditionType = "OR"
ConditionType_AND ConditionType = "AND"
)
const (
ConditionTokenType_SQL ConditionTokenType = "sql"
ConditionTokenType_FUNC ConditionTokenType = "func"
ConditionTokenType_PARAM ConditionTokenType = "param"
ConditionTokenType_STRING ConditionTokenType = "string"
)
const (
ConditionOperator_IS_NULL ConditionOperator = "IS NULL"
ConditionOperator_IS_NOT_NULL ConditionOperator = "IS NOT NULL"
ConditionOperator_EQ ConditionOperator = "="
ConditionOperator_NE ConditionOperator = "!="
ConditionOperator_GT ConditionOperator = ">"
ConditionOperator_GE ConditionOperator = ">="
ConditionOperator_LT ConditionOperator = "<"
ConditionOperator_LE ConditionOperator = "<="
ConditionOperator_LIKE ConditionOperator = "LIKE"
ConditionOperator_NOT_LIKE ConditionOperator = "NOT LIKE"
ConditionOperator_IN ConditionOperator = "IN"
ConditionOperator_NOT_IN ConditionOperator = "NOT IN"
ConditionOperator_REGEXP ConditionOperator = "REGEXP"
ConditionOperator_NOT_REGEXP ConditionOperator = "NOT REGEXP"
)
const (
OrderByDirection_ASC OrderByDirection = db.ORDER_ASC
OrderByDirection_DESC OrderByDirection = db.ORDER_DESC
)
type Orm interface {
SetGlobalParams(g GlobalParams) Orm
SetGlobalParams(g req.GlobalParams) Orm
GetModel(params ...string) Model
SetRelationModel(m Model) Model
SetQueryField(qf QueryField) error
SetQueryField(qf req.QueryField) error
SetOrderBy(params []OrderBy) error
SetCondition(cond Condition) error
SetCondition(cond *condition.Condition) error
SetController(ctr OrmController) error
Execute(OrmExecute) (any, error)
Clone(tx *db.Transaction) Orm
@ -83,9 +56,9 @@ type Relation interface {
AppendTo(Model)
Type() RelationType
SetType(RelationType)
SetCondition(Condition) Condition
SetPrependCondition(Condition) Condition
GetCondition() Condition
SetCondition(*condition.Condition) *condition.Condition
SetPrependCondition(*condition.Condition) *condition.Condition
GetCondition() *condition.Condition
GetRelationResource() string
GetRelationField() string
GetRelationForeignKey() string
@ -94,26 +67,26 @@ type Relation interface {
type Join interface {
Relation
GetCode() string
GetResource() Resource
GetResource() req.Resource
// GetDependencies(items []ResRelation, dependencies ...string) []string
Inject(dbBuilder *db.Builder, m Model)
}
type Model interface {
Relation
ModelParam
condition.TokenValue
GetCode() string
GetPrimaryKey() string
GetQueryFieldsStruct(extends ...reflect.StructField) any
GetQueryFieldsSliceStruct(fields ...reflect.StructField) any
GetAttribute() map[string]any
GetResult() reflect.Value
GetResource() Resource
GetResource() req.Resource
QueryBuilder() *db.Builder
GetTransaction() *db.Transaction
SetQueryField(QueryField)
SetQueryField(req.QueryField)
SetRelationResult(code string, vItems reflect.Value)
GetJoinsCode() []string
SetAuthDB(ResAuthDB)
SetAuthDB(req.ResAuthDB)
SetOrderBy(params ...OrderBy) Model
SetGroupBy(params ...GroupBy) Model
SetJoin(Join) Model
@ -130,43 +103,8 @@ type Model interface {
// Exists() (bool, error)
}
type ModelParam interface {
GetParam(k string) GlobalParams
GetGlobalParamsUser() User
}
type OrmController interface {
AuthDB() ResAuthDB
}
type Condition interface {
Type() ConditionType
IsEmpty() bool
IsNotEmpty() bool
IsAlwaysRight() bool
ToSql(ModelParam) db.Expression
AppendTo(Condition)
SetExpr(ConditionExpr) Condition
SetCondition(Condition) Condition
SetMatchPrefix(string) Condition
GetFields(operator ConditionOperator, types ...ConditionTokenType) map[string]string
GetFieldsValue(m ModelParam, isWithResource bool) map[string]any
}
type ConditionExpr interface {
GetField() string
GetFieldResource() string
GetOperator() ConditionOperator
SetMatchPrefix(string) ConditionExpr
AppendTo(Condition)
ToSql(m ModelParam) db.Expression
GetTokenName() string
GetTokenType() ConditionTokenType
GetTokenValue(ModelParam) any
GetTokenSqlValue(ModelParam) string
IsIgnoreEmptyParma(ModelParam) bool
AuthDB() req.ResAuthDB
}
type OrderBy interface {
@ -192,13 +130,13 @@ type QueryWithRecursive interface {
// @param rForeignKey 关联外键, 如 id
type NewOrmRelation func(t RelationType, m Model, rResource, rField, rForeignKey string) Model
type NewOrmJoin func(t RelationType, res Resource, alias, rResource, rField, rForeignKey string) Join
type NewOrmJoin func(t RelationType, res req.Resource, alias, rResource, rField, rForeignKey string) Join
type NewOrmCondition func(typ ConditionType, describe string) Condition
type NewOrmCondition func(typ ConditionType, describe string) *condition.Condition
type NewOrmConditionExpr func(rResource, rField, token string, operator ConditionOperator, tType ConditionTokenType, ignoreEmptyParma bool) ConditionExpr
type NewOrmConditionExpr func(rResource, rField, token string, operator ConditionOperator, tType ConditionTokenType, ignoreEmptyParma bool) *condition.ConditionExpr
type NewOrmConditionFuncExpr func(rResource, rField, token string, operator ConditionOperator, tType ConditionTokenType, ignoreEmptyParma bool, fn, fnParam string) ConditionExpr
type NewOrmConditionFuncExpr func(rResource, rField, token string, operator ConditionOperator, tType ConditionTokenType, ignoreEmptyParma bool, fn, fnParam string) *condition.ConditionExpr
type NewOrmQueryWithRecursive func(pField, cField string, root any, isWithoutCondition bool, depth int) QueryWithRecursive
@ -206,8 +144,8 @@ type NewOrmOrderBy func(sql string, direction OrderByDirection) OrderBy
type NewOrmGroupBy func(sql string) GroupBy
type NewOrmModel func(res Resource, code, name string) Model
type NewOrmModel func(res req.Resource, code, name string) Model
type NewOrm func(res Resource, tx *db.Transaction) Orm
type NewOrm func(res req.Resource, tx *db.Transaction) Orm
type GetOrmConditionByRes func(categoryUuid string, describe string) Condition
type GetOrmConditionByRes func(categoryUuid string, describe string) *condition.Condition

View File

@ -1,6 +1,7 @@
package contracts
import (
"git.fsdpf.net/go/req"
"github.com/samber/do"
"github.com/samber/lo"
)
@ -8,25 +9,25 @@ import (
type ResEvent string
type ResListener interface {
Insert(new map[string]any, u User, id int64) error
Update(new map[string]any, u User, old map[string]any) error
Delete(old map[string]any, u User) error
GetResource() Resource
Insert(new map[string]any, u req.User, id int64) error
Update(new map[string]any, u req.User, old map[string]any) error
Delete(old map[string]any, u req.User) error
GetResource() req.Resource
GetCode() string
}
type BaseListener struct {
Container *do.Injector
res Resource // 监听资源
code string // code
events []string // 监听动作
res req.Resource // 监听资源
code string // code
events []string // 监听动作
}
func (this BaseListener) GetCode() string {
return this.code
}
func (this BaseListener) GetResource() Resource {
func (this BaseListener) GetResource() req.Resource {
return this.res
}
@ -34,18 +35,18 @@ func (this BaseListener) HasEvent(event string) bool {
return lo.Contains(this.events, event)
}
func (BaseListener) Insert(new map[string]any, u User, id int64) error {
func (BaseListener) Insert(new map[string]any, u req.User, id int64) error {
return nil
}
func (BaseListener) Update(new map[string]any, u User, old map[string]any) error {
func (BaseListener) Update(new map[string]any, u req.User, old map[string]any) error {
return nil
}
func (BaseListener) Delete(old map[string]any, u User) error {
func (BaseListener) Delete(old map[string]any, u req.User) error {
return nil
}
func NewBaseListener(code string, res Resource, container *do.Injector) *BaseListener {
func NewBaseListener(code string, res req.Resource, container *do.Injector) *BaseListener {
return &BaseListener{code: code, res: res, Container: container}
}

View File

@ -1,111 +1,6 @@
package contracts
import (
"reflect"
"git.fsdpf.net/go/db"
"git.fsdpf.net/go/db/schema"
)
type ResDataType string
type ResConditionType string
type ResConditionTokenType string
type ResConditionOperator string
type ResAuthDB int
type QueryDataType string
const (
// 关闭权限过滤
ResAuthOff ResAuthDB = iota
// 开启权限过滤, 不包括关联资源
ResAuthOn
// 开启权限过滤, 包括关联资源
ResAuthAll
)
const (
ResDataType_String ResDataType = "string"
ResDataType_Text ResDataType = "text"
ResDataType_Integer ResDataType = "integer"
ResDataType_SmallInteger ResDataType = "smallInteger"
ResDataType_Decimal ResDataType = "decimal"
ResDataType_Boolean ResDataType = "boolean"
ResDataType_Json ResDataType = "json"
ResDataType_Enum ResDataType = "enum"
ResDataType_Timestamp ResDataType = "timestamp"
ResDataType_Date ResDataType = "date"
ResDataType_Datetime ResDataType = "dateTime"
)
const (
QueryDataType_Number QueryDataType = "number"
QueryDataType_Integer QueryDataType = "integer"
QueryDataType_Float QueryDataType = "float"
QueryDataType_String QueryDataType = "string"
QueryDataType_Bool QueryDataType = "bool"
QueryDataType_Array QueryDataType = "array"
QueryDataType_Json QueryDataType = "json"
)
const (
QueryField_IsExpr = 1 << iota
QueryField_IsOmitempty
QueryField_Ignored
)
type Resource interface {
GetUuid() string
GetName() string
GetCode() string
GetPrimarykey() string
GetFields() []ResField
GetField(string) (ResField, bool)
HasField(string) bool
BeginTransaction() (*db.Transaction, error)
GetTable() db.Expression
GetDBConn() *db.Connection
GetDBBuilder() *db.Builder
GetDBTable(params ...any) *db.Builder
GetAuthDBTable(u User, params ...any) *db.Builder
GetStruct(extends ...reflect.StructField) any
GetSliceStruct(extends ...reflect.StructField) any
WithRolesCondition(b *db.Builder, t string, u User) error
// 是否虚拟资源
IsVirtual() bool
// 是否系统资源
IsSystem() bool
}
type ResField interface {
GetName() string
GetCode() string
GetCodeResource() string
GetDataType() ResDataType
GetQueryDataType() QueryDataType
GetRawDefault(driver string) db.Expression
ToStructField(tags ...string) reflect.StructField
ToValue(any) any
ToBlueprint(table *schema.Blueprint) *schema.ColumnDefinition
ToQueryField(t QueryDataType, alias string, options int) QueryField
}
type QueryField interface {
ResField
Type() QueryDataType
Alias() string
GetCodeOrAlias() string
IsExpr() bool
IsOmitempty() bool
Ignored() bool
SetOptions(int) QueryField
ToSql() db.Expression
ToStructField(tags ...string) reflect.StructField
}
import "git.fsdpf.net/go/req"
// 资源
type GetResource func(code string) (Resource, bool)
type GetResource func(code string) (req.Resource, bool)

View File

@ -1,10 +0,0 @@
package contracts
import (
"net/http"
)
type HttpResponse interface {
Get(path ...string) GlobalParams
Send(w http.ResponseWriter, r *http.Request)
}

View File

@ -1,139 +0,0 @@
package contracts
import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/gorilla/websocket"
)
type RouteMethod string
type RouteCategory string
type RouteService string
type RouteParamType string
type RouteParamCategory string
type RouteCtx struct {
Name string
}
const (
RouteMethod_GET RouteMethod = "GET"
RouteMethod_POST RouteMethod = "POST"
RouteMethod_PUT RouteMethod = "PUT"
RouteMethod_DELETE RouteMethod = "DELETE"
)
const (
RouteCategory_WS RouteCategory = "ws"
RouteCategory_GRPC RouteCategory = "grpc"
RouteCategory_FUNC RouteCategory = "func"
RouteCategory_SHOW RouteCategory = "show"
RouteCategory_QUERY RouteCategory = "query"
RouteCategory_STORE RouteCategory = "store"
RouteCategory_DESTROY RouteCategory = "destroy"
RouteCategory_STRUCTURE RouteCategory = "structure"
)
const (
RouteService_API RouteService = "api"
RouteService_FSM RouteService = "fsm"
RouteService_LIST RouteService = "list"
RouteService_XLSX RouteService = "xlsx"
RouteService_IMPORT RouteService = "import"
RouteService_PRINT RouteService = "print"
RouteService_LAYOUT RouteService = "layout"
RouteService_GRID_LAYOUT RouteService = "grid-layout"
RouteService_GRID_LAYOUT_FORM RouteService = "grid-layout-form"
RouteService_ECHART RouteService = "echart"
RouteService_APPROVAL RouteService = "approval"
RouteService_SELECTOR RouteService = "selector"
RouteService_LIST_DETAIL RouteService = "list-detail"
RouteService_LIST_DATA_STORE RouteService = "list-data-store"
RouteService_LIST_GRID_LAYOUT RouteService = "list-grid-layout"
RouteService_LIST_CONDITION_LAYOUT RouteService = "list-condition-layout"
RouteService_LIST_OPERATIONS_ACCESS RouteService = "list-operations-access"
)
const (
RouteParam_STRING RouteParamType = "string"
RouteParam_BOOL RouteParamType = "bool"
RouteParam_NUMBER RouteParamType = "number"
RouteParam_INTEGER RouteParamType = "integer"
RouteParam_FLOAT RouteParamType = "float"
RouteParam_JSON RouteParamType = "json"
RouteParam_ARRAY RouteParamType = "array"
RouteParam_ANY RouteParamType = "any"
)
const (
RouteParamCategory_ROUTER RouteParamCategory = "router"
RouteParamCategory_HEADER RouteParamCategory = "header"
RouteParamCategory_PARAM RouteParamCategory = "param"
)
func (k RouteCtx) String() string {
return k.Name
}
type RouteMiddleware interface {
HttpMiddleware(r Route) func(next http.Handler) http.Handler
}
type Router interface {
Call(r *http.Request, code string, params map[string]any, category ...RouteCategory) (HttpResponse, error)
Get(uuid string, category ...RouteCategory) (Route, bool)
Register(cr chi.Router)
RefreshRoutes() error
}
type Route interface {
GetUuid() string
GetCode() string
GetPrimaryKey() string
GetUri() string
GetUris() []string
GetParamValues(*http.Request, ...RouteParam) (GlobalParams, error)
GetResource() Resource
GetCategory() RouteCategory
GetService() RouteService
GetRoles() []string
MakeRequest(r *http.Request, params map[string]any) (*http.Request, error)
}
type RouteParam interface {
GetCode() string
GetDataType() RouteParamType
GetCategory() RouteParamCategory
IsRequired() bool
InjectRequestToGlobalParams(*http.Request, GlobalParams) error
}
type WsClientGroup string
type WsClientID uint
// type WsClient struct {
// User
// Group WsClientGroup
// Socket *websocket.Conn
// }
type WsClient interface {
User
Socket() *websocket.Conn
WsClientID() WsClientID
WsClientGroup() WsClientGroup
WsClientManage() WsClientManage
Lock()
Unlock()
}
type WsClientManage interface {
Register(WsClient) bool
Unregister(WsClient)
GetClients(func(WsClient) bool) []WsClient
}
type WsChannelManage interface {
Channel(string) WsClientManage
}

View File

@ -1,228 +0,0 @@
package support
import (
"time"
"github.com/samber/lo"
"github.com/spf13/cast"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
"git.fsdpf.net/go/contracts"
)
type GlobalParams struct {
user *contracts.User
gjson gjson.Result
}
// 获取用户信息
func (this GlobalParams) User() contracts.User {
return *this.user
}
// 获取指定路径的 value
func (this GlobalParams) Get(key string) contracts.GlobalParams {
return &GlobalParams{
user: this.user,
gjson: this.gjson.Get(key),
}
}
//
func (this GlobalParams) Array() []contracts.GlobalParams {
return lo.Map(this.gjson.Array(), func(item gjson.Result, _ int) contracts.GlobalParams {
return &GlobalParams{user: this.user, gjson: gjson.Parse(item.Raw)}
})
}
// 获取golang原始类型
func (this GlobalParams) Value() any {
return this.gjson.Value()
}
func (this GlobalParams) Raw() string {
return this.gjson.Raw
}
// 设置json值
func (this *GlobalParams) Set(p string, v any) bool {
if s, err := sjson.Set(this.Raw(), p, v); err != nil {
return false
} else {
this.gjson = gjson.Parse(s)
}
return true
}
// 设置json原始值
func (this *GlobalParams) SetRaw(p, v string) bool {
if s, err := sjson.SetRaw(this.Raw(), p, v); err != nil {
return false
} else {
this.gjson = gjson.Parse(s)
}
return true
}
// 删除路径内容
func (this *GlobalParams) Delete(p string) bool {
if s, err := sjson.Delete(this.Raw(), p); err != nil {
return false
} else {
this.gjson = gjson.Parse(s)
}
return true
}
// 路径包裹
func (this *GlobalParams) Wrapped(p string) contracts.GlobalParams {
return this.AppendTo("", p)
}
// 包裹内容
func (this *GlobalParams) AppendTo(root, p string) contracts.GlobalParams {
if root != "" && !gjson.Valid(root) {
root = ""
}
return NewGlobalParam(lo.Must(sjson.SetRaw(root, p, this.Raw())), *this.user)
}
// 判断值是否存在
func (this GlobalParams) Exists() bool {
return this.gjson.Exists()
}
// to Bool
func (this GlobalParams) Bool() bool {
return cast.ToBool(this.Value())
}
// to Time
func (this GlobalParams) Time() time.Time {
return cast.ToTime(this.Value())
}
// to Location Time
func (this GlobalParams) TimeInDefaultLocation(location *time.Location) time.Time {
return cast.ToTimeInDefaultLocation(this, location)
}
// to float64
func (this GlobalParams) Float64() float64 {
return cast.ToFloat64(this.Value())
}
// to float32
func (this GlobalParams) Float32() float32 {
return cast.ToFloat32(this.Value())
}
// to int64
func (this GlobalParams) Int64() int64 {
return cast.ToInt64(this.Value())
}
// to int32
func (this GlobalParams) Int32() int32 {
return cast.ToInt32(this.Value())
}
// to int16
func (this GlobalParams) Int16() int16 {
return cast.ToInt16(this.Value())
}
// to int8
func (this GlobalParams) Int8() int8 {
return cast.ToInt8(this.Value())
}
// to int
func (this GlobalParams) Int() int {
return cast.ToInt(this.Value())
}
// to uint
func (this GlobalParams) Uint() uint {
return cast.ToUint(this.Value())
}
// to uint64
func (this GlobalParams) Uint64() uint64 {
return cast.ToUint64(this.Value())
}
// to uint32
func (this GlobalParams) Uint32() uint32 {
return cast.ToUint32(this.Value())
}
// to uint16
func (this GlobalParams) Uint16() uint16 {
return cast.ToUint16(this.Value())
}
// to uint8
func (this GlobalParams) Uint8() uint8 {
return cast.ToUint8(this.Value())
}
// to string
func (this GlobalParams) String() string {
return cast.ToString(this.Value())
}
// to map[string]string
func (this GlobalParams) StringMapString() map[string]string {
return cast.ToStringMapString(this.Value())
}
// to map[string][]string
func (this GlobalParams) StringMapStringSlice() map[string][]string {
return cast.ToStringMapStringSlice(this.Value())
}
// to map[string]bool
func (this GlobalParams) StringMapBool() map[string]bool {
return cast.ToStringMapBool(this.Value())
}
// to map[string]int
func (this GlobalParams) StringMapInt() map[string]int {
return cast.ToStringMapInt(this.Value())
}
// to map[string]int64
func (this GlobalParams) StringMapInt64() map[string]int64 {
return cast.ToStringMapInt64(this.Value())
}
// to map[string]any
func (this GlobalParams) StringMap() map[string]any {
return cast.ToStringMap(this.Value())
}
// to []any
func (this GlobalParams) Slice() []any {
return cast.ToSlice(this.Value())
}
// to []bool
func (this GlobalParams) BoolSlice() []bool {
return cast.ToBoolSlice(this.Value())
}
// to []string
func (this GlobalParams) StringSlice() []string {
return cast.ToStringSlice(this.Value())
}
// to []int
func (this GlobalParams) IntSlice() []int {
return cast.ToIntSlice(this.Value())
}
func NewGlobalParam(data string, user contracts.User) contracts.GlobalParams {
return &GlobalParams{user: &user, gjson: gjson.Parse(data)}
}

View File

@ -5,34 +5,36 @@ import (
"reflect"
"strings"
"git.fsdpf.net/go/condition"
"git.fsdpf.net/go/contracts"
"git.fsdpf.net/go/db"
"git.fsdpf.net/go/utils"
"github.com/samber/do"
"github.com/samber/lo"
"github.com/spf13/cast"
)
type Operation struct {
Uuid string `json:"uuid"`
Name string `json:"name"`
Code string `json:"code"`
Icon string `json:"icon"`
Size string `json:"size"`
Block bool `json:"block"`
Ghost bool `json:"ghost"`
Shape string `json:"shape"`
Type string `json:"type"`
PopConfirm any `json:"popConfirm,omitempty"`
Widget string `json:"widget"`
WidgetType string `json:"widgetType"`
WidgetProps any `json:"widgetProps"`
WidgetSetting any `json:"widgetSetting"`
WidgetContainerSetting any `json:"widgetContainerSetting"`
IsRefresh int `json:"isRefresh"`
NoAuthType string `json:"noAuthType"`
Roles []string `json:"-"`
Children []Operation `json:"children,omitempty"`
AccessCondition contracts.Condition `json:"-"`
Uuid string `json:"uuid"`
Name string `json:"name"`
Code string `json:"code"`
Icon string `json:"icon"`
Size string `json:"size"`
Block bool `json:"block"`
Ghost bool `json:"ghost"`
Shape string `json:"shape"`
Type string `json:"type"`
PopConfirm any `json:"popConfirm,omitempty"`
Widget string `json:"widget"`
WidgetType string `json:"widgetType"`
WidgetProps any `json:"widgetProps"`
WidgetSetting any `json:"widgetSetting"`
WidgetContainerSetting any `json:"widgetContainerSetting"`
IsRefresh int `json:"isRefresh"`
NoAuthType string `json:"noAuthType"`
Roles []string `json:"-"`
Children []Operation `json:"children,omitempty"`
AccessCondition *condition.Condition `json:"-"`
}
type OperationAccess struct {
@ -42,14 +44,13 @@ type OperationAccess struct {
func (o Operation) ToDBColumn(model contracts.Model, container *do.Injector) (column db.Expression, field reflect.StructField) {
GetOrmConditionByRes := do.MustInvoke[contracts.GetOrmConditionByRes](container)
NewOrmCondition := do.MustInvoke[contracts.NewOrmCondition](container)
uuid := strings.ReplaceAll(o.Uuid, "-", "_")
// 主键
pk := model.GetCode() + "." + model.GetPrimaryKey()
cond := lo.Ternary(o.AccessCondition != nil, o.AccessCondition, NewOrmCondition(contracts.ConditionType_AND, "operation access condition "+uuid))
cond := lo.Ternary(o.AccessCondition != nil, o.AccessCondition, condition.New(condition.Describe("operation access condition "+uuid)))
if c := GetOrmConditionByRes(o.Uuid, "operation access condition "+uuid); c.IsNotEmpty() {
cond.SetCondition(c)
@ -63,7 +64,7 @@ func (o Operation) ToDBColumn(model contracts.Model, container *do.Injector) (co
// 主键类型
tPkType := reflect.TypeOf("")
if tPk, ok := GetStructField(model.GetQueryFieldsStruct(), model.GetPrimaryKey()); ok {
if tPk, ok := utils.GetStructField(model.GetQueryFieldsStruct(), model.GetPrimaryKey()); ok {
tPkType = tPk.Type
}
field = reflect.StructField{
@ -149,7 +150,7 @@ func NewOperationAccess(m contracts.Model) OperationAccess {
// 主键类型
tPkType := reflect.String
if tPk, ok := GetStructField(m.GetQueryFieldsStruct(), m.GetPrimaryKey()); ok {
if tPk, ok := utils.GetStructField(m.GetQueryFieldsStruct(), m.GetPrimaryKey()); ok {
switch tPk.Type.Kind() {
case reflect.Int, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint32, reflect.Uint64:

View File

@ -8,6 +8,7 @@ import (
"strings"
"git.fsdpf.net/go/contracts"
"git.fsdpf.net/go/req"
"github.com/gorilla/websocket"
"github.com/samber/lo"
)
@ -40,8 +41,8 @@ var wsUpgrader = websocket.Upgrader{
},
}
func (this RawResponse) Get(path ...string) contracts.GlobalParams {
return lo.Ternary(len(path) == 0, NewGlobalParam(string(this.raw), nil), NewGlobalParam(string(this.raw), nil).Get(strings.Join(path, ".")))
func (this RawResponse) Get(path ...string) req.GlobalParams {
return lo.Ternary(len(path) == 0, req.NewGlobalParam(string(this.raw), nil), req.NewGlobalParam(string(this.raw), nil).Get(strings.Join(path, ".")))
}
func (this RawResponse) Send(w http.ResponseWriter, r *http.Request) {
@ -54,8 +55,8 @@ func (this RawResponse) Send(w http.ResponseWriter, r *http.Request) {
}
}
func (this JsonResponse) Get(path ...string) contracts.GlobalParams {
return lo.Ternary(len(path) == 0, NewGlobalParam(string(this.raw), nil), NewGlobalParam(string(this.raw), nil).Get(strings.Join(path, ".")))
func (this JsonResponse) Get(path ...string) req.GlobalParams {
return lo.Ternary(len(path) == 0, req.NewGlobalParam(string(this.raw), nil), req.NewGlobalParam(string(this.raw), nil).Get(strings.Join(path, ".")))
}
func (this JsonResponse) Send(w http.ResponseWriter, r *http.Request) {
@ -69,12 +70,12 @@ func (this JsonResponse) Send(w http.ResponseWriter, r *http.Request) {
}
}
func (this MsgResponse) Get(path ...string) contracts.GlobalParams {
func (this MsgResponse) Get(path ...string) req.GlobalParams {
if resp, err := json.Marshal(map[string]any{
"code": this.code,
"msg": this.msg,
}); err == nil {
return lo.Ternary(len(path) == 0, NewGlobalParam(string(resp), nil), NewGlobalParam(string(resp), nil).Get(strings.Join(path, ".")))
return lo.Ternary(len(path) == 0, req.NewGlobalParam(string(resp), nil), req.NewGlobalParam(string(resp), nil).Get(strings.Join(path, ".")))
}
return nil
@ -88,13 +89,13 @@ func (this MsgResponse) Send(w http.ResponseWriter, r *http.Request) {
}
}
func (this ErrResponse) Get(path ...string) contracts.GlobalParams {
func (this ErrResponse) Get(path ...string) req.GlobalParams {
if resp, err := json.Marshal(map[string]any{
"code": this.code,
"msg": this.msg,
"error": string(this.stack),
}); err == nil {
return lo.Ternary(len(path) == 0, NewGlobalParam(string(resp), nil), NewGlobalParam(string(resp), nil).Get(strings.Join(path, ".")))
return lo.Ternary(len(path) == 0, req.NewGlobalParam(string(resp), nil), req.NewGlobalParam(string(resp), nil).Get(strings.Join(path, ".")))
}
return nil
@ -108,12 +109,12 @@ func (this ErrResponse) Send(w http.ResponseWriter, r *http.Request) {
}
}
func (this FileResponse) Get(path ...string) contracts.GlobalParams {
func (this FileResponse) Get(path ...string) req.GlobalParams {
if resp, err := json.Marshal(map[string]any{
"name": this.name,
"disposition": this.disposition,
}); err == nil {
return lo.Ternary(len(path) == 0, NewGlobalParam(string(resp), nil), NewGlobalParam(string(resp), nil).Get(strings.Join(path, ".")))
return lo.Ternary(len(path) == 0, req.NewGlobalParam(string(resp), nil), req.NewGlobalParam(string(resp), nil).Get(strings.Join(path, ".")))
}
return nil
@ -130,31 +131,31 @@ func (this FileResponse) Send(w http.ResponseWriter, r *http.Request) {
}
}
func NewRawResponse(b []byte) contracts.HttpResponse {
func NewRawResponse(b []byte) req.HttpResponse {
return &RawResponse{raw: b}
}
func NewJsonResponse(b []byte) contracts.HttpResponse {
func NewJsonResponse(b []byte) req.HttpResponse {
return &JsonResponse{raw: b}
}
func NewFileResponse(name string, disposition string) contracts.HttpResponse {
func NewFileResponse(name string, disposition string) req.HttpResponse {
return &FileResponse{name: name, disposition: disposition}
}
func NewMsgResponse(msg string, code int) contracts.HttpResponse {
func NewMsgResponse(msg string, code int) req.HttpResponse {
return &MsgResponse{msg: msg, code: code}
}
func NewErrResponse(err *contracts.Err) contracts.HttpResponse {
func NewErrResponse(err *contracts.Err) req.HttpResponse {
return NewJsonResponse([]byte(fmt.Sprintf(`{"code": %d, "msg": %q}`, err.Code, err.Error())))
}
func HttpResponse(data any) contracts.HttpResponse {
func HttpResponse(data any) req.HttpResponse {
var err error
// fmt.Printf("%#v \n", data)
switch v := data.(type) {
case contracts.HttpResponse:
case req.HttpResponse:
return v
case contracts.Errno:
return NewMsgResponse(v.Error(), v.Code)

View File

@ -1,175 +0,0 @@
package support
import (
"fmt"
"os"
"path/filepath"
"reflect"
"strings"
"unsafe"
"github.com/spf13/cast"
)
func GetFieldValue(i any, k string) any {
v := reflect.ValueOf(i)
var kv reflect.Value
if v.Kind() == reflect.Ptr {
v = reflect.Indirect(v)
}
if v.Kind() == reflect.Struct {
kv = v.FieldByName(k)
} else if v.Kind() == reflect.Map {
for _, key := range v.MapKeys() {
if key.String() == k {
kv = v.MapIndex(key)
}
}
}
switch kv.Kind() {
case reflect.String:
return kv.String()
case reflect.Bool:
return kv.Bool()
case reflect.Float32, reflect.Float64:
return kv.Float()
case reflect.Int, reflect.Int64:
return int(kv.Int())
case reflect.Invalid:
return nil
}
return kv.Interface()
}
func GetStructField(item any, key string) (field reflect.StructField, ok bool) {
vItem := reflect.TypeOf(item)
if vItem.Kind() == reflect.Ptr {
vItem = vItem.Elem()
}
if vItem.Kind() != reflect.Struct {
return field, false
}
return vItem.FieldByName(UcFirst(key))
}
func InterfaceToSlice(i any) (ret []any) {
rv := reflect.ValueOf(i)
if rv.Kind() == reflect.Ptr {
rv = reflect.Indirect(rv)
}
if rv.Kind() != reflect.Slice {
panic("请传入切片类型数据")
}
for i := 0; i < rv.Len(); i++ {
ret = append(ret, rv.Index(i).Interface())
}
return ret
}
func SliceConvert(origSlice any, newSliceType reflect.Type) any {
sv := reflect.ValueOf(origSlice)
if sv.Kind() != reflect.Slice {
panic(fmt.Sprintf("无效切片类型 %T (来源)", origSlice))
}
if newSliceType.Kind() != reflect.Slice {
panic(fmt.Sprintf("无效切片类型 %T (目标)", newSliceType))
}
// 生成新类型的切片
newSlice := reflect.New(newSliceType)
// hdr指向到新生成切片的SliceHeader
hdr := (*reflect.SliceHeader)(unsafe.Pointer(newSlice.Pointer()))
var newElemSize = int(sv.Type().Elem().Size()) / int(newSliceType.Elem().Size())
// 设置SliceHeader的CapLen以及数组的ptr
hdr.Cap = sv.Cap() * newElemSize
hdr.Len = sv.Len() * newElemSize
hdr.Data = uintptr(sv.Pointer())
return newSlice.Elem().Interface()
}
func DeepSearch(m map[string]any, path []string) map[string]any {
for _, k := range path {
m2, ok := m[k]
if !ok {
// intermediate key does not exist
// => create it and continue from there
m3 := make(map[string]interface{})
m[k] = m3
m = m3
continue
}
m3, ok := m2.(map[string]interface{})
if !ok {
// intermediate key is a value
// => replace with a new map
m3 = make(map[string]interface{})
m[k] = m3
}
// continue search from here
m = m3
}
return m
}
func MergeMap(shadow map[string]any, m map[string]any) map[string]any {
if shadow == nil {
shadow = make(map[string]any)
}
var m2 map[string]any
for k, val := range m {
switch val.(type) {
case map[string]any:
m2 = val.(map[string]any)
case map[any]any:
m2 = cast.ToStringMap(val)
default:
// immediate value
shadow[k] = val
continue
}
// recursively merge to shadow map
shadow[k] = MergeMap(cast.ToStringMap(shadow[k]), m2)
}
return shadow
}
func UcFirst(s string) string {
if s == "" {
return ""
}
return strings.ToUpper(s[:1]) + s[1:]
}
func StudlyCase(s string) string {
return strings.Replace(strings.Title(strings.Replace(s, "-", " ", -1)), " ", "", -1)
}
func GetAbsPath(s string) string {
if strings.HasPrefix(s, "/") {
return s
} else if dir, err := os.Getwd(); err == nil {
return filepath.Join(dir, s)
}
return s
}

View File

@ -1,46 +0,0 @@
package support
import (
"testing"
)
func TestDeepSearch(t *testing.T) {
m := map[string]any{
"a": 1,
"b": map[string]any{
"c": 2,
},
}
mb := DeepSearch(m, []string{"b", "a"})
t.Log(m)
mb["cc"] = "3"
t.Log(m)
}
func TestMergeMap(t *testing.T) {
m1 := map[string]any{
"a": 1,
"b": map[string]any{
"c": 2,
"a": 1,
"b": map[string]any{
"c": 2,
"a": 1,
},
},
}
m2 := map[string]any{
"a": 11,
"b": map[string]any{
"c": 22,
"cc": 33,
},
}
t.Log(MergeMap(m1, m2))
}

53
user.go
View File

@ -1,53 +0,0 @@
package contracts
type UserRuntime struct {
platform string
saas string
}
// 账号运行平台
func (this UserRuntime) Platform() string {
return this.platform
}
// 账号运行租户
func (this UserRuntime) SaaS() string {
return this.saas
}
type User interface {
Runtime() UserRuntime
// 用户ID
ID() int64
// 用户UUID
Uuid() string
// 用户名称
Username() string
// 用户昵称
Nickname() string
// 用户明细
GetUserInfo() map[string]any
// 用户权限
Roles() []string
// 用户权限检查
HasUserRoles(roles ...string) bool
// 是否匿名用户
IsAnonymous() bool
}
// 用户
type GetUser func(uuid string, options ...UserRuntimeOption) (User, error)
type UserRuntimeOption func(option *UserRuntime)
func UserRuntimePlatform(value string) UserRuntimeOption {
return func(option *UserRuntime) {
option.platform = value
}
}
func UserRuntimeSaaS(value string) UserRuntimeOption {
return func(option *UserRuntime) {
option.saas = value
}
}

View File

@ -4,6 +4,7 @@ import (
"net/http"
"git.fsdpf.net/go/db"
"git.fsdpf.net/go/req"
)
type UserApprovalExecute int
@ -51,9 +52,9 @@ type UserApproval interface {
// 审批流名称
Name() string
// 发起审批请求
RequestApproval(Route, *http.Request) any
RequestApproval(req.Route, *http.Request) any
// 判断发起审批请求权限
HasUserRoles(User) bool
HasUserRoles(req.User) bool
// 获取审批列表标记字段值
Execute(id int64, status UserApprovalExecute, r *http.Request, tx *db.Transaction) (current, next UserApprovalFlow, err error)
}

35
ws.go Normal file
View File

@ -0,0 +1,35 @@
package contracts
import (
"git.fsdpf.net/go/req"
"github.com/gorilla/websocket"
)
type WsClientGroup string
type WsClientID uint
// type WsClient struct {
// User
// Group WsClientGroup
// Socket *websocket.Conn
// }
type WsClient interface {
req.User
Socket() *websocket.Conn
WsClientID() WsClientID
WsClientGroup() WsClientGroup
WsClientManage() WsClientManage
Lock()
Unlock()
}
type WsClientManage interface {
Register(WsClient) bool
Unregister(WsClient)
GetClients(func(WsClient) bool) []WsClient
}
type WsChannelManage interface {
Channel(string) WsClientManage
}