Compare commits
No commits in common. "master" and "v0.0.6" have entirely different histories.
|
@ -84,14 +84,9 @@ func BuildConditions(ctx context.Context, r *http.Request, query *Query, schemas
|
|||
}
|
||||
//如果是多选的话,直接使用IN操作
|
||||
columnName := row.Column + "[]"
|
||||
if qs.Has(columnName) {
|
||||
if len(qs[columnName]) > 1 {
|
||||
if qs.Has(columnName) && len(qs[columnName]) > 1 {
|
||||
query.AndFilterWhere(newConditionWithOperator("IN", row.Column, qs[columnName]))
|
||||
continue
|
||||
} else if len(qs[columnName]) == 1 {
|
||||
query.AndFilterWhere(newCondition(row.Column, qs[columnName][0]))
|
||||
continue
|
||||
}
|
||||
}
|
||||
formValue = qs.Get(row.Column)
|
||||
switch row.Format {
|
||||
|
|
126
model.go
126
model.go
|
@ -28,12 +28,10 @@ import (
|
|||
type Model struct {
|
||||
naming types.Naming //命名规则
|
||||
value reflect.Value //模块值
|
||||
modelValue any //模块实例
|
||||
db *gorm.DB //数据库
|
||||
primaryKey string //主键
|
||||
urlPrefix string //url前缀
|
||||
disableDomain bool //禁用域
|
||||
permissionChecker types.PermissionChecker //权限检查
|
||||
schemaLookup types.SchemaLookupFunc //获取schema的函数
|
||||
valueLookup types.ValueLookupFunc //查看域
|
||||
statement *gorm.Statement //字段声明
|
||||
|
@ -41,7 +39,6 @@ type Model struct {
|
|||
response types.HttpWriter //HTTP响应
|
||||
hookMgr *hookManager //钩子管理器
|
||||
dirname string //存放文件目录
|
||||
scenarios []string //场景
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -68,18 +65,7 @@ func (m *Model) getHook() *hookManager {
|
|||
|
||||
// hasScenario 判断是否有该场景
|
||||
func (m *Model) hasScenario(s string) bool {
|
||||
if len(m.scenarios) == 0 {
|
||||
return true
|
||||
}
|
||||
return slices.Contains(m.scenarios, s)
|
||||
}
|
||||
|
||||
// hasPermission 判断是否有权限
|
||||
func (m *Model) hasPermission(ctx context.Context, s string) (err error) {
|
||||
if m.permissionChecker != nil {
|
||||
return m.permissionChecker.CheckPermission(ctx, m.Permission(s))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// setValue 设置字段的值
|
||||
|
@ -172,7 +158,7 @@ func (m *Model) buildReporterCountColumns(ctx context.Context, dest types.Report
|
|||
modelType = modelType.Elem()
|
||||
}
|
||||
columns := make([]string, 0)
|
||||
for i := range modelType.NumField() {
|
||||
for i := 0; i < modelType.NumField(); i++ {
|
||||
field := modelType.Field(i)
|
||||
scenarios := field.Tag.Get("scenarios")
|
||||
if !hasToken(types.ScenarioList, scenarios) {
|
||||
|
@ -233,28 +219,7 @@ func (m *Model) ModuleName() string {
|
|||
|
||||
// TableName 表的名称
|
||||
func (m *Model) TableName() string {
|
||||
return m.naming.TableName
|
||||
}
|
||||
|
||||
func (m *Model) Naming() types.Naming {
|
||||
return m.naming
|
||||
}
|
||||
|
||||
func (m *Model) Value() reflect.Value {
|
||||
return m.value
|
||||
}
|
||||
|
||||
func (m *Model) SetDB(db *gorm.DB) *gorm.DB {
|
||||
m.db = db
|
||||
return m.db
|
||||
}
|
||||
|
||||
func (m *Model) HasScenario(s string) bool {
|
||||
return m.hasScenario(s)
|
||||
}
|
||||
|
||||
func (m *Model) HasPermission(ctx context.Context, s string) (err error) {
|
||||
return m.hasPermission(ctx, s)
|
||||
return m.naming.ModuleName
|
||||
}
|
||||
|
||||
// Fields 返回搜索的模型的字段
|
||||
|
@ -262,36 +227,9 @@ func (m *Model) Fields() []*schema.Field {
|
|||
return m.statement.Schema.Fields
|
||||
}
|
||||
|
||||
// Permission 获取权限
|
||||
// 权限示例: "module.model.scenario"
|
||||
// 比如: organize:user:list, organize:user:create
|
||||
func (m *Model) Permission(scenario string) string {
|
||||
if pm, ok := m.modelValue.(PermissionModel); ok {
|
||||
return pm.GetPermission(scenario)
|
||||
}
|
||||
ss := make([]string, 0, 4)
|
||||
switch scenario {
|
||||
case types.ScenarioList:
|
||||
ss = append(ss, m.naming.ModuleName, m.naming.Singular, "list")
|
||||
case types.ScenarioView:
|
||||
ss = append(ss, m.naming.ModuleName, m.naming.Singular, "detail")
|
||||
case types.ScenarioCreate:
|
||||
ss = append(ss, m.naming.ModuleName, m.naming.Singular, "create")
|
||||
case types.ScenarioUpdate:
|
||||
ss = append(ss, m.naming.ModuleName, m.naming.Singular, "update")
|
||||
case types.ScenarioDelete:
|
||||
ss = append(ss, m.naming.ModuleName, m.naming.Singular, "delete")
|
||||
case types.ScenarioExport:
|
||||
ss = append(ss, m.naming.ModuleName, m.naming.Singular, "export")
|
||||
case types.ScenarioImport:
|
||||
ss = append(ss, m.naming.ModuleName, m.naming.Singular, "import")
|
||||
}
|
||||
return strings.Join(ss, ":")
|
||||
}
|
||||
|
||||
// Uri 获取请求的uri
|
||||
func (m *Model) Uri(scenario string) string {
|
||||
ss := make([]string, 0, 4)
|
||||
ss := make([]string, 4)
|
||||
if m.urlPrefix != "" {
|
||||
ss = append(ss, m.urlPrefix)
|
||||
}
|
||||
|
@ -336,7 +274,6 @@ func (m *Model) Method(scenario string) string {
|
|||
|
||||
// Search 实现通过HTTP方法查找数据
|
||||
func (m *Model) Search(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var (
|
||||
ok bool
|
||||
err error
|
||||
|
@ -355,14 +292,6 @@ func (m *Model) Search(w http.ResponseWriter, r *http.Request) {
|
|||
reporter types.Reporter
|
||||
namerTable tableNamer
|
||||
)
|
||||
if !m.hasScenario(types.ScenarioList) {
|
||||
m.response.Failure(w, types.RequestDenied, scenarioNotAllow, nil)
|
||||
return
|
||||
}
|
||||
if err = m.hasPermission(r.Context(), types.ScenarioList); err != nil {
|
||||
m.response.Failure(w, types.RequestDenied, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
qs = r.URL.Query()
|
||||
page, _ = strconv.Atoi(qs.Get("page"))
|
||||
pageSize, _ = strconv.Atoi(qs.Get("pagesize"))
|
||||
|
@ -463,14 +392,6 @@ func (m *Model) Create(w http.ResponseWriter, r *http.Request) {
|
|||
domainName string
|
||||
modelValue reflect.Value
|
||||
)
|
||||
if !m.hasScenario(types.ScenarioCreate) {
|
||||
m.response.Failure(w, types.RequestDenied, scenarioNotAllow, nil)
|
||||
return
|
||||
}
|
||||
if err = m.hasPermission(r.Context(), types.ScenarioCreate); err != nil {
|
||||
m.response.Failure(w, types.RequestDenied, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
modelValue = reflect.New(m.value.Type())
|
||||
model = modelValue.Interface()
|
||||
if err = json.NewDecoder(r.Body).Decode(modelValue.Interface()); err != nil {
|
||||
|
@ -552,14 +473,6 @@ func (m *Model) Update(w http.ResponseWriter, r *http.Request) {
|
|||
modelValue reflect.Value
|
||||
oldValues map[string]any
|
||||
)
|
||||
if !m.hasScenario(types.ScenarioUpdate) {
|
||||
m.response.Failure(w, types.RequestDenied, scenarioNotAllow, nil)
|
||||
return
|
||||
}
|
||||
if err = m.hasPermission(r.Context(), types.ScenarioUpdate); err != nil {
|
||||
m.response.Failure(w, types.RequestDenied, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
idStr := m.findPrimaryKey(m.Uri(types.ScenarioUpdate), r)
|
||||
modelValue = reflect.New(m.value.Type())
|
||||
model = modelValue.Interface()
|
||||
|
@ -651,14 +564,6 @@ func (m *Model) Delete(w http.ResponseWriter, r *http.Request) {
|
|||
model any
|
||||
modelValue reflect.Value
|
||||
)
|
||||
if !m.hasScenario(types.ScenarioDelete) {
|
||||
m.response.Failure(w, types.RequestDenied, scenarioNotAllow, nil)
|
||||
return
|
||||
}
|
||||
if err = m.hasPermission(r.Context(), types.ScenarioDelete); err != nil {
|
||||
m.response.Failure(w, types.RequestDenied, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
idStr := m.findPrimaryKey(m.Uri(types.ScenarioDelete), r)
|
||||
modelValue = reflect.New(m.value.Type())
|
||||
model = modelValue.Interface()
|
||||
|
@ -714,14 +619,6 @@ func (m *Model) View(w http.ResponseWriter, r *http.Request) {
|
|||
scenario string
|
||||
domainName string
|
||||
)
|
||||
if !m.hasScenario(types.ScenarioView) {
|
||||
m.response.Failure(w, types.RequestDenied, scenarioNotAllow, nil)
|
||||
return
|
||||
}
|
||||
if err = m.hasPermission(r.Context(), types.ScenarioView); err != nil {
|
||||
m.response.Failure(w, types.RequestDenied, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
qs = r.URL.Query()
|
||||
idStr := m.findPrimaryKey(m.Uri(types.ScenarioUpdate), r)
|
||||
modelValue = reflect.New(m.value.Type())
|
||||
|
@ -760,12 +657,8 @@ func (m *Model) Export(w http.ResponseWriter, r *http.Request) {
|
|||
fp *os.File
|
||||
modelValue reflect.Value
|
||||
)
|
||||
if !m.hasScenario(types.ScenarioExport) {
|
||||
m.response.Failure(w, types.RequestDenied, scenarioNotAllow, nil)
|
||||
return
|
||||
}
|
||||
if err = m.hasPermission(r.Context(), types.ScenarioExport); err != nil {
|
||||
m.response.Failure(w, types.RequestDenied, err.Error(), nil)
|
||||
if !m.hasScenario(types.ScenarioList) {
|
||||
m.response.Failure(w, types.RequestDenied, "request denied", nil)
|
||||
return
|
||||
}
|
||||
domainName = m.valueLookup(types.FieldDomain, w, r)
|
||||
|
@ -1006,14 +899,6 @@ func (m *Model) Import(w http.ResponseWriter, r *http.Request) {
|
|||
qs url.Values
|
||||
extraFields map[string]string
|
||||
)
|
||||
if !m.hasScenario(types.ScenarioImport) {
|
||||
m.response.Failure(w, types.RequestDenied, scenarioNotAllow, nil)
|
||||
return
|
||||
}
|
||||
if err = m.hasPermission(r.Context(), types.ScenarioImport); err != nil {
|
||||
m.response.Failure(w, types.RequestDenied, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
domainName = m.valueLookup(types.FieldDomain, w, r)
|
||||
if schemas, err = m.schemaLookup(r.Context(), m.getDB(), domainName, m.naming.ModuleName, m.naming.TableName, types.ScenarioCreate); err != nil {
|
||||
m.response.Failure(w, types.RequestRecordNotFound, "record not found", nil)
|
||||
|
@ -1089,7 +974,6 @@ func newModel(v any, db *gorm.DB, naming types.Naming) *Model {
|
|||
value: reflect.Indirect(reflect.ValueOf(v)),
|
||||
valueLookup: defaultValueLookup,
|
||||
}
|
||||
model.modelValue = reflect.New(model.value.Type()).Interface()
|
||||
model.statement = &gorm.Statement{
|
||||
DB: model.getDB(),
|
||||
ConnPool: model.getDB().ConnPool,
|
||||
|
|
38
options.go
38
options.go
|
@ -12,29 +12,11 @@ type options struct {
|
|||
db *gorm.DB
|
||||
router types.HttpRouter
|
||||
writer types.HttpWriter
|
||||
permissionChecker types.PermissionChecker
|
||||
valueLookup types.ValueLookupFunc
|
||||
formatter *Formatter
|
||||
resourceDirectory string
|
||||
}
|
||||
|
||||
type Option func(o *options)
|
||||
|
||||
func (o *options) Clone() *options {
|
||||
return &options{
|
||||
urlPrefix: o.urlPrefix,
|
||||
moduleName: o.moduleName,
|
||||
disableDomain: o.disableDomain,
|
||||
db: o.db,
|
||||
router: o.router,
|
||||
writer: o.writer,
|
||||
permissionChecker: o.permissionChecker,
|
||||
formatter: o.formatter,
|
||||
resourceDirectory: o.resourceDirectory,
|
||||
valueLookup: o.valueLookup,
|
||||
}
|
||||
}
|
||||
|
||||
// WithDB 设置DB
|
||||
func WithDB(db *gorm.DB) Option {
|
||||
return func(o *options) {
|
||||
|
@ -49,12 +31,6 @@ func WithUriPrefix(s string) Option {
|
|||
}
|
||||
}
|
||||
|
||||
func WithValueLookup(f types.ValueLookupFunc) Option {
|
||||
return func(o *options) {
|
||||
o.valueLookup = f
|
||||
}
|
||||
}
|
||||
|
||||
// WithModuleName 模块名称
|
||||
func WithModuleName(s string) Option {
|
||||
return func(o *options) {
|
||||
|
@ -89,17 +65,3 @@ func WithFormatter(s *Formatter) Option {
|
|||
o.formatter = s
|
||||
}
|
||||
}
|
||||
|
||||
// WithPermissionChecker 配置PermissionChecker
|
||||
func WithPermissionChecker(s types.PermissionChecker) Option {
|
||||
return func(o *options) {
|
||||
o.permissionChecker = s
|
||||
}
|
||||
}
|
||||
|
||||
// WithResourceDirectory 配置资源目录
|
||||
func WithResourceDirectory(s string) Option {
|
||||
return func(o *options) {
|
||||
o.resourceDirectory = s
|
||||
}
|
||||
}
|
||||
|
|
131
rest.go
131
rest.go
|
@ -492,13 +492,21 @@ func Init(cbs ...Option) (err error) {
|
|||
}
|
||||
|
||||
// AutoMigrate 自动合并表的schema
|
||||
func AutoMigrate(ctx context.Context, model any, cbs ...Option) (modelValue *Model, err error) {
|
||||
func AutoMigrate(ctx context.Context, model any, cbs ...Option) (err error) {
|
||||
var (
|
||||
opts *options
|
||||
table string
|
||||
router types.HttpRouter
|
||||
)
|
||||
opts = globalOpts.Clone()
|
||||
opts = &options{
|
||||
db: globalOpts.db,
|
||||
router: globalOpts.router,
|
||||
writer: globalOpts.writer,
|
||||
formatter: globalOpts.formatter,
|
||||
moduleName: globalOpts.moduleName,
|
||||
urlPrefix: globalOpts.urlPrefix,
|
||||
disableDomain: globalOpts.disableDomain,
|
||||
}
|
||||
for _, cb := range cbs {
|
||||
cb(opts)
|
||||
}
|
||||
|
@ -506,22 +514,14 @@ func AutoMigrate(ctx context.Context, model any, cbs ...Option) (modelValue *Mod
|
|||
return
|
||||
}
|
||||
//路由模块处理
|
||||
singularizeTable := inflector.Singularize(table)
|
||||
modelValue = newModel(model, opts.db, types.Naming{
|
||||
Pluralize: inflector.Pluralize(singularizeTable),
|
||||
Singular: singularizeTable,
|
||||
modelValue := newModel(model, opts.db, types.Naming{
|
||||
Pluralize: inflector.Pluralize(table),
|
||||
Singular: inflector.Singularize(table),
|
||||
ModuleName: opts.moduleName,
|
||||
TableName: table,
|
||||
})
|
||||
if scenarioModel, ok := model.(types.ScenarioModel); ok {
|
||||
modelValue.scenarios = scenarioModel.Scenario()
|
||||
}
|
||||
if opts.valueLookup != nil {
|
||||
modelValue.valueLookup = opts.valueLookup
|
||||
}
|
||||
modelValue.hookMgr = hookMgr
|
||||
modelValue.schemaLookup = VisibleSchemas
|
||||
modelValue.permissionChecker = opts.permissionChecker
|
||||
if opts.router != nil {
|
||||
router = opts.router
|
||||
}
|
||||
|
@ -652,128 +652,63 @@ func VisibleSchemas(ctx context.Context, db *gorm.DB, domain, moduleName, tableN
|
|||
}
|
||||
|
||||
// ModelTypes 查询指定模型的类型
|
||||
func ModelTypes[T any](ctx context.Context, db *gorm.DB, model any, domainName, labelColumn, valueColumn string) (values []*types.TypeValue[T], err error) {
|
||||
func ModelTypes(ctx context.Context, db *gorm.DB, model any, domainName, labelColumn, valueColumn string) (values []*types.TypeValue) {
|
||||
tx := db.WithContext(ctx)
|
||||
result := make([]map[string]any, 0, 10)
|
||||
if domainName == "" {
|
||||
err = tx.Model(model).Select(labelColumn, valueColumn).Scan(&result).Error
|
||||
tx.Model(model).Select(labelColumn, valueColumn).Scan(&result)
|
||||
} else {
|
||||
err = tx.Model(model).Select(labelColumn, valueColumn).Where("domain=?", domainName).Scan(&result).Error
|
||||
tx.Model(model).Select(labelColumn, valueColumn).Where("domain=?", domainName).Scan(&result)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
values = make([]*types.TypeValue[T], 0, len(result))
|
||||
values = make([]*types.TypeValue, 0, len(result))
|
||||
for _, pairs := range result {
|
||||
feed := &types.TypeValue[T]{}
|
||||
feed := &types.TypeValue{}
|
||||
for k, v := range pairs {
|
||||
if k == labelColumn {
|
||||
if s, ok := v.(string); ok {
|
||||
feed.Label = s
|
||||
} else {
|
||||
feed.Label = fmt.Sprint(s)
|
||||
}
|
||||
continue
|
||||
feed.Label = v
|
||||
}
|
||||
if k == valueColumn {
|
||||
if p, ok := v.(T); ok {
|
||||
feed.Value = p
|
||||
}
|
||||
continue
|
||||
feed.Value = v
|
||||
}
|
||||
}
|
||||
values = append(values, feed)
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// ModelTiers 查询指定模型的层级数据
|
||||
func ModelTiers[T comparable](ctx context.Context, db *gorm.DB, model any, domainName, parentColumn, labelColumn, valueColumn string) (values []*types.TierValue[T], err error) {
|
||||
tx := db.WithContext(ctx)
|
||||
result := make([]map[string]any, 0, 10)
|
||||
if domainName == "" {
|
||||
err = tx.Model(model).Select(parentColumn, labelColumn, valueColumn).Scan(&result).Error
|
||||
} else {
|
||||
err = tx.Model(model).Select(parentColumn, labelColumn, valueColumn).Where("domain=?", domainName).Scan(&result).Error
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
values = make([]*types.TierValue[T], 0, len(result))
|
||||
for _, pairs := range result {
|
||||
feed := &types.TierValue[T]{}
|
||||
for k, v := range pairs {
|
||||
if k == labelColumn {
|
||||
if s, ok := v.(string); ok {
|
||||
feed.Label = s
|
||||
} else {
|
||||
feed.Label = fmt.Sprint(s)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if k == valueColumn {
|
||||
if p, ok := v.(T); ok {
|
||||
feed.Value = p
|
||||
}
|
||||
continue
|
||||
}
|
||||
if k == parentColumn {
|
||||
if p, ok := v.(T); ok {
|
||||
feed.Parent = p
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
values = append(values, feed)
|
||||
}
|
||||
var none T
|
||||
return recursiveTier(none, values), nil
|
||||
return values
|
||||
}
|
||||
|
||||
// GetFieldValue 获取模型某个字段的值
|
||||
func GetFieldValue(stmt *gorm.Statement, refValue reflect.Value, column string) any {
|
||||
func GetFieldValue(stmt *gorm.Statement, refValue reflect.Value, column string) interface{} {
|
||||
var (
|
||||
rawField *schema.Field
|
||||
idx = -1
|
||||
)
|
||||
refVal := reflect.Indirect(refValue)
|
||||
for _, field := range stmt.Schema.Fields {
|
||||
for i, field := range stmt.Schema.Fields {
|
||||
if field.DBName == column || field.Name == column {
|
||||
rawField = field
|
||||
idx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if rawField == nil {
|
||||
if idx > -1 {
|
||||
return refVal.Field(idx).Interface()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
var targetValue reflect.Value
|
||||
targetValue = refVal
|
||||
for _, i := range rawField.StructField.Index {
|
||||
targetValue = targetValue.Field(i)
|
||||
}
|
||||
return targetValue.Interface()
|
||||
}
|
||||
|
||||
// SetFieldValue 设置模型某个字段的值
|
||||
func SetFieldValue(stmt *gorm.Statement, refValue reflect.Value, column string, value any) {
|
||||
var (
|
||||
rawField *schema.Field
|
||||
idx = -1
|
||||
)
|
||||
refVal := reflect.Indirect(refValue)
|
||||
for _, field := range stmt.Schema.Fields {
|
||||
for i, field := range stmt.Schema.Fields {
|
||||
if field.DBName == column || field.Name == column {
|
||||
rawField = field
|
||||
idx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if rawField == nil {
|
||||
return
|
||||
if idx > -1 {
|
||||
refVal.Field(idx).Set(reflect.ValueOf(value))
|
||||
}
|
||||
var targetValue reflect.Value
|
||||
targetValue = refVal
|
||||
for _, i := range rawField.StructField.Index {
|
||||
targetValue = targetValue.Field(i)
|
||||
}
|
||||
targetValue.Set(reflect.ValueOf(value))
|
||||
}
|
||||
|
||||
// SafeSetFileValue 安全设置模型某个字段的值
|
||||
|
|
9
types.go
9
types.go
|
@ -21,10 +21,6 @@ var (
|
|||
allowMethods = []string{http.MethodPut, http.MethodPost}
|
||||
)
|
||||
|
||||
var (
|
||||
scenarioNotAllow = "request not allowed"
|
||||
)
|
||||
|
||||
type (
|
||||
httpWriter struct {
|
||||
}
|
||||
|
@ -44,11 +40,6 @@ type (
|
|||
HttpTableName(req *http.Request) string
|
||||
}
|
||||
|
||||
// 权限模型定义
|
||||
PermissionModel interface {
|
||||
GetPermission(scenario string) string
|
||||
}
|
||||
|
||||
//创建后的回调,这个回调不在事物内
|
||||
afterCreated interface {
|
||||
AfterCreated(ctx context.Context, tx *gorm.DB)
|
||||
|
|
|
@ -2,10 +2,9 @@ package types
|
|||
|
||||
import (
|
||||
"context"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -108,36 +107,17 @@ type (
|
|||
Handle(method string, uri string, handler http.HandlerFunc)
|
||||
}
|
||||
|
||||
// 权限检测器
|
||||
PermissionChecker interface {
|
||||
CheckPermission(ctx context.Context, permission string) error
|
||||
}
|
||||
|
||||
// 模型场景
|
||||
ScenarioModel interface {
|
||||
Scenario() []string
|
||||
}
|
||||
|
||||
// TypeValue 键值对数据
|
||||
TypeValue[T any] struct {
|
||||
Label string `json:"label"`
|
||||
Value T `json:"value"`
|
||||
}
|
||||
|
||||
//TierValue 层级数据
|
||||
TierValue[T comparable] struct {
|
||||
Label string `json:"label"`
|
||||
Value T `json:"value"`
|
||||
Parent T `json:"-"`
|
||||
Used bool `json:"-"`
|
||||
Children []*TierValue[T] `json:"children"`
|
||||
TypeValue struct {
|
||||
Label any `json:"label"`
|
||||
Value any `json:"value"`
|
||||
}
|
||||
|
||||
// NestedValue 层级数据
|
||||
NestedValue[T any] struct {
|
||||
Label string `json:"label"`
|
||||
Value T `json:"value"`
|
||||
Children []*NestedValue[T] `json:"children,omitempty"`
|
||||
NestedValue struct {
|
||||
Label any `json:"label"`
|
||||
Value any `json:"value"`
|
||||
Children []*NestedValue `json:"children,omitempty"`
|
||||
}
|
||||
|
||||
//ValueLookupFunc 查找域的函数
|
||||
|
@ -249,17 +229,3 @@ type (
|
|||
Status string `json:"status"`
|
||||
}
|
||||
)
|
||||
|
||||
func (t *TierValue[T]) HasChild(value T) bool {
|
||||
for _, child := range t.Children {
|
||||
if child.Value == value {
|
||||
return true
|
||||
}
|
||||
if len(child.Children) > 0 {
|
||||
if child.HasChild(value) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
17
utils.go
17
utils.go
|
@ -4,8 +4,6 @@ import (
|
|||
"reflect"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"git.nobla.cn/golang/rest/types"
|
||||
)
|
||||
|
||||
func hasToken(hack string, need string) bool {
|
||||
|
@ -45,18 +43,3 @@ func isEmpty(val any) bool {
|
|||
return reflect.DeepEqual(val, reflect.Zero(v.Type()).Interface())
|
||||
}
|
||||
}
|
||||
|
||||
func recursiveTier[T comparable](parent T, values []*types.TierValue[T]) []*types.TierValue[T] {
|
||||
items := make([]*types.TierValue[T], 0, len(values)/2)
|
||||
for idx, row := range values {
|
||||
if row.Used {
|
||||
continue
|
||||
}
|
||||
if row.Parent == parent {
|
||||
values[idx].Used = true
|
||||
row.Children = recursiveTier(row.Value, values)
|
||||
items = append(items, row)
|
||||
}
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue