package support import ( "encoding/json" "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 *condition.Condition `json:"-"` } type OperationAccess struct { typ reflect.Kind // 只能为 reflect.Int 和 reflect.String data map[string][]any } func (o Operation) ToDBColumn(model contracts.Model, container *do.Injector) (column db.Expression, field reflect.StructField) { GetOrmConditions := do.MustInvoke[contracts.GetOrmConditions](container) uuid := strings.ReplaceAll(o.Uuid, "-", "_") // 主键 pk := model.GetCode() + "." + model.GetPrimaryKey() cond := lo.Ternary(o.AccessCondition != nil, o.AccessCondition, condition.New(condition.Describe("operation access condition "+uuid))) if c := GetOrmConditions(o.Uuid, condition.Describe("operation access condition "+uuid)); c.IsNotEmpty() { cond.SetCondition(c) } if cond.IsEmpty() { column = db.Raw(pk + " as `u_" + uuid + "`") } else { column = db.Raw("if(" + string(cond.ToSql(model)) + ", " + pk + ", 0) as `u_" + uuid + "`") } // 主键类型 tPkType := reflect.TypeOf("") if tPk, ok := utils.GetStructField(model.GetQueryFieldsStruct(), model.GetPrimaryKey()); ok { tPkType = tPk.Type } field = reflect.StructField{ Name: "U_" + uuid, Tag: reflect.StructTag(`db:"u_` + uuid + `"`), Type: tPkType, } return column, field } func (oa OperationAccess) Get(k string) []any { items, ok := oa.data[k] if !ok { return nil } return items } func (oa *OperationAccess) Set(k string, v []any) error { oa.data[k] = []any{} return oa.Push(k, v...) } func (oa *OperationAccess) Push(k string, ids ...any) error { if _, ok := oa.data[k]; !ok { oa.Set(k, []any{}) } for i := 0; i < len(ids); i++ { if v, err := oa.Convert(ids[i]); err != nil { return err } else if !lo.Contains(oa.data[k], v) { oa.data[k] = append(oa.data[k], v) } } return nil } func (oa OperationAccess) Merge(item OperationAccess) error { for k, v := range item.data { oa.Push(k, v...) } return nil } func (oa OperationAccess) Convert(v any) (any, error) { if oa.typ == reflect.Int { return cast.ToIntE(v) } return cast.ToStringE(v) } func (oa OperationAccess) Exist(k string, v any) bool { items, ok := oa.data[k] if !ok { return false } flag, err := oa.Convert(v) if err != nil { return false } return lo.Contains(items, flag) } func (oa OperationAccess) MarshalJSON() ([]byte, error) { temp := [][2]any{} for k, v := range oa.data { temp = append(temp, [2]any{k, v}) } return json.Marshal(temp) } func NewOperationAccess(m contracts.Model) OperationAccess { // 主键类型 tPkType := reflect.String 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: tPkType = reflect.Int } } return OperationAccess{typ: tPkType, data: map[string][]any{}} }