添加操作记录支持
This commit is contained in:
parent
56d50536fc
commit
7098529421
|
@ -0,0 +1,189 @@
|
||||||
|
package aeusadmin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.nobla.cn/golang/aeus-admin/models"
|
||||||
|
"git.nobla.cn/golang/rest"
|
||||||
|
"git.nobla.cn/golang/rest/types"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
recorder struct {
|
||||||
|
Domain string `json:"domain"`
|
||||||
|
User string `json:"user"`
|
||||||
|
Module string `json:"module"`
|
||||||
|
Table string `json:"table"`
|
||||||
|
Action string `json:"action"`
|
||||||
|
PrimaryKey any `json:"primary_key"`
|
||||||
|
Diffs []*types.DiffAttr `json:"diffs"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type ActivityRecorder struct {
|
||||||
|
db *gorm.DB
|
||||||
|
ctx context.Context
|
||||||
|
batchTimeout time.Duration
|
||||||
|
BatchSize int
|
||||||
|
ch chan *models.Activity
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ActivityRecorder) onAfterCreate(ctx context.Context, tx *gorm.DB, model any, diff []*types.DiffAttr) {
|
||||||
|
v := ctx.Value(rest.RuntimeScopeKey)
|
||||||
|
if v == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
runtimeScope, ok := v.(*types.RuntimeScope)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data := &models.Activity{}
|
||||||
|
data.Uid = runtimeScope.User
|
||||||
|
data.Module = runtimeScope.ModuleName
|
||||||
|
data.Table = runtimeScope.TableName
|
||||||
|
data.Action = types.ScenarioCreate
|
||||||
|
if buf, err := json.Marshal(diff); err == nil {
|
||||||
|
data.Data = string(buf)
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case s.ch <- data:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ActivityRecorder) onAfterUpdate(ctx context.Context, tx *gorm.DB, model any, diff []*types.DiffAttr) {
|
||||||
|
v := ctx.Value(rest.RuntimeScopeKey)
|
||||||
|
if v == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
runtimeScope, ok := v.(*types.RuntimeScope)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data := &models.Activity{}
|
||||||
|
data.Uid = runtimeScope.User
|
||||||
|
data.Module = runtimeScope.ModuleName
|
||||||
|
data.Table = runtimeScope.TableName
|
||||||
|
data.Action = types.ScenarioUpdate
|
||||||
|
if diff == nil {
|
||||||
|
diff = make([]*types.DiffAttr, 0)
|
||||||
|
}
|
||||||
|
diff = append(diff, &types.DiffAttr{
|
||||||
|
Column: "primary_key",
|
||||||
|
NewValue: runtimeScope.PrimaryKeyValue,
|
||||||
|
})
|
||||||
|
if buf, err := json.Marshal(diff); err == nil {
|
||||||
|
data.Data = string(buf)
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case s.ch <- data:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ActivityRecorder) onAfterDelete(ctx context.Context, tx *gorm.DB, model any) {
|
||||||
|
v := ctx.Value(rest.RuntimeScopeKey)
|
||||||
|
if v == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
runtimeScope, ok := v.(*types.RuntimeScope)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data := &models.Activity{}
|
||||||
|
data.Uid = runtimeScope.User
|
||||||
|
data.Module = runtimeScope.ModuleName
|
||||||
|
data.Table = runtimeScope.TableName
|
||||||
|
data.Action = types.ScenarioDelete
|
||||||
|
diff := make([]*types.DiffAttr, 0, 1)
|
||||||
|
diff = append(diff, &types.DiffAttr{
|
||||||
|
Column: "primary_key",
|
||||||
|
NewValue: runtimeScope.PrimaryKeyValue,
|
||||||
|
})
|
||||||
|
if buf, err := json.Marshal(diff); err == nil {
|
||||||
|
data.Data = string(buf)
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case s.ch <- data:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ActivityRecorder) batchWrite(values []*models.Activity) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if len(values) <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = s.db.Create(values).Error; err != nil {
|
||||||
|
for _, row := range values {
|
||||||
|
s.db.Create(row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ActivityRecorder) writeLoop() {
|
||||||
|
var (
|
||||||
|
values []*models.Activity
|
||||||
|
)
|
||||||
|
timer := time.NewTimer(s.batchTimeout)
|
||||||
|
defer func() {
|
||||||
|
timer.Stop()
|
||||||
|
if len(values) > 0 {
|
||||||
|
s.batchWrite(values)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-s.ctx.Done():
|
||||||
|
return
|
||||||
|
case <-timer.C:
|
||||||
|
if len(values) > 0 {
|
||||||
|
s.batchWrite(values)
|
||||||
|
values = nil
|
||||||
|
}
|
||||||
|
timer.Reset(s.batchTimeout)
|
||||||
|
case msg, ok := <-s.ch:
|
||||||
|
if ok {
|
||||||
|
values = append(values, msg)
|
||||||
|
if len(values) > s.BatchSize {
|
||||||
|
s.batchWrite(values)
|
||||||
|
values = nil
|
||||||
|
timer.Reset(s.batchTimeout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ActivityRecorder) Recoder(scenes ...string) {
|
||||||
|
if len(scenes) == 0 {
|
||||||
|
scenes = []string{types.ScenarioCreate, types.ScenarioUpdate, types.ScenarioDelete}
|
||||||
|
}
|
||||||
|
for _, str := range scenes {
|
||||||
|
switch str {
|
||||||
|
case types.ScenarioCreate:
|
||||||
|
rest.OnAfterCreate(s.onAfterCreate)
|
||||||
|
case types.ScenarioUpdate:
|
||||||
|
rest.OnAfterUpdate(s.onAfterUpdate)
|
||||||
|
case types.ScenarioDelete:
|
||||||
|
rest.OnAfterDelete(s.onAfterDelete)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewActivityRecorder(ctx context.Context, db *gorm.DB) *ActivityRecorder {
|
||||||
|
s := &ActivityRecorder{
|
||||||
|
db: db,
|
||||||
|
ctx: ctx,
|
||||||
|
batchTimeout: time.Second,
|
||||||
|
BatchSize: 50,
|
||||||
|
ch: make(chan *models.Activity, 100),
|
||||||
|
}
|
||||||
|
go s.writeLoop()
|
||||||
|
return s
|
||||||
|
}
|
|
@ -34,6 +34,9 @@ func (t *ZH) Menu(model *rest.Model, label string) string {
|
||||||
if _, ok := model.Value().Interface().(models.Setting); ok {
|
if _, ok := model.Value().Interface().(models.Setting); ok {
|
||||||
return "参数设置"
|
return "参数设置"
|
||||||
}
|
}
|
||||||
|
if _, ok := model.Value().Interface().(models.Activity); ok {
|
||||||
|
return "操作记录"
|
||||||
|
}
|
||||||
return label
|
return label
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,10 @@ type (
|
||||||
Setting struct {
|
Setting struct {
|
||||||
pb.SettingModel
|
pb.SettingModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Activity struct {
|
||||||
|
pb.ActivityModel
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *User) GetMenu() *types.Menu {
|
func (m *User) GetMenu() *types.Menu {
|
||||||
|
@ -123,3 +127,22 @@ func (m *Setting) GetMenu() *types.Menu {
|
||||||
func (m *Setting) ModuleName() string {
|
func (m *Setting) ModuleName() string {
|
||||||
return "system"
|
return "system"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Activity) GetMenu() *types.Menu {
|
||||||
|
return &types.Menu{
|
||||||
|
Name: "SystemActivity",
|
||||||
|
Parent: "System",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Activity) Scenario() []string {
|
||||||
|
return []string{restTypes.ScenarioList}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Activity) ModuleName() string {
|
||||||
|
return "system"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Activity) GetPermission(s string) string {
|
||||||
|
return "system:activity:list"
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1188,6 +1188,128 @@ var _ interface {
|
||||||
ErrorName() string
|
ErrorName() string
|
||||||
} = SettingValidationError{}
|
} = SettingValidationError{}
|
||||||
|
|
||||||
|
// Validate checks the field values on Activity with the rules defined in the
|
||||||
|
// proto definition for this message. If any rules are violated, the first
|
||||||
|
// error encountered is returned, or nil if there are no violations.
|
||||||
|
func (m *Activity) Validate() error {
|
||||||
|
return m.validate(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateAll checks the field values on Activity with the rules defined in
|
||||||
|
// the proto definition for this message. If any rules are violated, the
|
||||||
|
// result is a list of violation errors wrapped in ActivityMultiError, or nil
|
||||||
|
// if none found.
|
||||||
|
func (m *Activity) ValidateAll() error {
|
||||||
|
return m.validate(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Activity) validate(all bool) error {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var errors []error
|
||||||
|
|
||||||
|
// no validation rules for Id
|
||||||
|
|
||||||
|
// no validation rules for CreatedAt
|
||||||
|
|
||||||
|
if l := utf8.RuneCountInString(m.GetUid()); l < 5 || l > 20 {
|
||||||
|
err := ActivityValidationError{
|
||||||
|
field: "Uid",
|
||||||
|
reason: "value length must be between 5 and 20 runes, inclusive",
|
||||||
|
}
|
||||||
|
if !all {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// no validation rules for Action
|
||||||
|
|
||||||
|
// no validation rules for Module
|
||||||
|
|
||||||
|
// no validation rules for Table
|
||||||
|
|
||||||
|
// no validation rules for Data
|
||||||
|
|
||||||
|
if len(errors) > 0 {
|
||||||
|
return ActivityMultiError(errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ActivityMultiError is an error wrapping multiple validation errors returned
|
||||||
|
// by Activity.ValidateAll() if the designated constraints aren't met.
|
||||||
|
type ActivityMultiError []error
|
||||||
|
|
||||||
|
// Error returns a concatenation of all the error messages it wraps.
|
||||||
|
func (m ActivityMultiError) Error() string {
|
||||||
|
msgs := make([]string, 0, len(m))
|
||||||
|
for _, err := range m {
|
||||||
|
msgs = append(msgs, err.Error())
|
||||||
|
}
|
||||||
|
return strings.Join(msgs, "; ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllErrors returns a list of validation violation errors.
|
||||||
|
func (m ActivityMultiError) AllErrors() []error { return m }
|
||||||
|
|
||||||
|
// ActivityValidationError is the validation error returned by
|
||||||
|
// Activity.Validate if the designated constraints aren't met.
|
||||||
|
type ActivityValidationError struct {
|
||||||
|
field string
|
||||||
|
reason string
|
||||||
|
cause error
|
||||||
|
key bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Field function returns field value.
|
||||||
|
func (e ActivityValidationError) Field() string { return e.field }
|
||||||
|
|
||||||
|
// Reason function returns reason value.
|
||||||
|
func (e ActivityValidationError) Reason() string { return e.reason }
|
||||||
|
|
||||||
|
// Cause function returns cause value.
|
||||||
|
func (e ActivityValidationError) Cause() error { return e.cause }
|
||||||
|
|
||||||
|
// Key function returns key value.
|
||||||
|
func (e ActivityValidationError) Key() bool { return e.key }
|
||||||
|
|
||||||
|
// ErrorName returns error name.
|
||||||
|
func (e ActivityValidationError) ErrorName() string { return "ActivityValidationError" }
|
||||||
|
|
||||||
|
// Error satisfies the builtin error interface
|
||||||
|
func (e ActivityValidationError) Error() string {
|
||||||
|
cause := ""
|
||||||
|
if e.cause != nil {
|
||||||
|
cause = fmt.Sprintf(" | caused by: %v", e.cause)
|
||||||
|
}
|
||||||
|
|
||||||
|
key := ""
|
||||||
|
if e.key {
|
||||||
|
key = "key for "
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"invalid %sActivity.%s: %s%s",
|
||||||
|
key,
|
||||||
|
e.field,
|
||||||
|
e.reason,
|
||||||
|
cause)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ error = ActivityValidationError{}
|
||||||
|
|
||||||
|
var _ interface {
|
||||||
|
Field() string
|
||||||
|
Reason() string
|
||||||
|
Key() bool
|
||||||
|
Cause() error
|
||||||
|
ErrorName() string
|
||||||
|
} = ActivityValidationError{}
|
||||||
|
|
||||||
// Validate checks the field values on LabelValue with the rules defined in the
|
// Validate checks the field values on LabelValue with the rules defined in the
|
||||||
// proto definition for this message. If any rules are violated, the first
|
// proto definition for this message. If any rules are violated, the first
|
||||||
// error encountered is returned, or nil if there are no violations.
|
// error encountered is returned, or nil if there are no violations.
|
||||||
|
|
|
@ -103,7 +103,7 @@ message Login {
|
||||||
};
|
};
|
||||||
int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment:"ID"}];
|
int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment:"ID"}];
|
||||||
int64 created_at = 2 [(aeus.field)={scenarios:"list;search;view;export",comment:"登录时间"}];
|
int64 created_at = 2 [(aeus.field)={scenarios:"list;search;view;export",comment:"登录时间"}];
|
||||||
string uid = 4 [(aeus.field)={gorm:"index;size:20",rule:"required",props:"readonly:update",format:"user",comment: "用户工号"},(validate.rules).string = {min_len: 5, max_len: 20}];
|
string uid = 4 [(aeus.field)={gorm:"index;size:20",rule:"required",props:"readonly:update",format:"user",comment: "用户"},(validate.rules).string = {min_len: 5, max_len: 20}];
|
||||||
string ip = 5 [(aeus.field)={gorm:"size:128",scenarios:"list;search;view;export",comment: "登录地址"}];
|
string ip = 5 [(aeus.field)={gorm:"size:128",scenarios:"list;search;view;export",comment: "登录地址"}];
|
||||||
string browser = 6 [(aeus.field)={gorm:"size:128",scenarios:"list;view;export",comment: "浏览器"}];
|
string browser = 6 [(aeus.field)={gorm:"size:128",scenarios:"list;view;export",comment: "浏览器"}];
|
||||||
string os = 7 [(aeus.field)={gorm:"size:128",scenarios:"list;view;export",comment: "操作系统"}];
|
string os = 7 [(aeus.field)={gorm:"size:128",scenarios:"list;view;export",comment: "操作系统"}];
|
||||||
|
@ -126,6 +126,20 @@ message Setting {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Activity 活动记录
|
||||||
|
message Activity {
|
||||||
|
option (aeus.rest) = {
|
||||||
|
table: "activities"
|
||||||
|
};
|
||||||
|
int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment:"ID"}];
|
||||||
|
int64 created_at = 2 [(aeus.field)={scenarios:"search;search;view;export",comment:"创建时间"}];
|
||||||
|
string uid = 3 [(aeus.field)={gorm:"index;size:20",rule:"required",props:"readonly:update",format:"user",comment: "用户"},(validate.rules).string = {min_len: 5, max_len: 20}];
|
||||||
|
string action = 4 [(aeus.field)={props:"match:exactly",gorm:"index;size:20;not null;default:''",comment:"行为",enum:"create:新建#198754;update:更新#f09d00;delete:删除#e63757",scenarios:"search;list;create;update;view;export"}];
|
||||||
|
string module = 5 [(aeus.field)={gorm:"size:60;not null;default:''",comment:"模块",scenarios:"search;list;create;update;view;export"}];
|
||||||
|
string table = 6 [(aeus.field)={gorm:"size:60;not null;default:''",comment:"数据",scenarios:"list;create;update;view;export"}];
|
||||||
|
string data = 7 [(aeus.field)={gorm:"size:10240;not null;default:''",comment:"内容",scenarios:"list;create;update;view;export"}];
|
||||||
|
}
|
||||||
|
|
||||||
message LabelValue {
|
message LabelValue {
|
||||||
string label = 1;
|
string label = 1;
|
||||||
string value = 2;
|
string value = 2;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by protoc-gen-go-aeus. DO NOT EDIT.
|
// Code generated by protoc-gen-go-aeus. DO NOT EDIT.
|
||||||
// source: organize.proto
|
// source: organize.proto
|
||||||
// date: 2025-06-17 15:01:15
|
// date: 2025-06-17 18:12:28
|
||||||
|
|
||||||
package pb
|
package pb
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by protoc-gen-go-aeus. DO NOT EDIT.
|
// Code generated by protoc-gen-go-aeus. DO NOT EDIT.
|
||||||
// source: organize.proto
|
// source: organize.proto
|
||||||
// date: 2025-06-17 15:01:15
|
// date: 2025-06-17 18:12:28
|
||||||
|
|
||||||
package pb
|
package pb
|
||||||
|
|
||||||
|
@ -431,7 +431,7 @@ func NewDepartmentModel() *DepartmentModel {
|
||||||
type LoginModel struct {
|
type LoginModel struct {
|
||||||
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"ID"`
|
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"ID"`
|
||||||
CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"登录时间" scenarios:"list;search;view;export"`
|
CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"登录时间" scenarios:"list;search;view;export"`
|
||||||
Uid string `json:"uid" yaml:"uid" xml:"uid" gorm:"index;size:20" comment:"用户工号" format:"user" props:"readonly:update" rule:"required"`
|
Uid string `json:"uid" yaml:"uid" xml:"uid" gorm:"index;size:20" comment:"用户" format:"user" props:"readonly:update" rule:"required"`
|
||||||
Ip string `json:"ip" yaml:"ip" xml:"ip" gorm:"size:128" comment:"登录地址" scenarios:"list;search;view;export"`
|
Ip string `json:"ip" yaml:"ip" xml:"ip" gorm:"size:128" comment:"登录地址" scenarios:"list;search;view;export"`
|
||||||
Browser string `json:"browser" yaml:"browser" xml:"browser" gorm:"size:128" comment:"浏览器" scenarios:"list;view;export"`
|
Browser string `json:"browser" yaml:"browser" xml:"browser" gorm:"size:128" comment:"浏览器" scenarios:"list;view;export"`
|
||||||
Os string `json:"os" yaml:"os" xml:"os" gorm:"size:128" comment:"操作系统" scenarios:"list;view;export"`
|
Os string `json:"os" yaml:"os" xml:"os" gorm:"size:128" comment:"操作系统" scenarios:"list;view;export"`
|
||||||
|
@ -566,3 +566,71 @@ func (m *SettingModel) FindAll(db *gorm.DB, query any, args ...any) (err error)
|
||||||
func NewSettingModel() *SettingModel {
|
func NewSettingModel() *SettingModel {
|
||||||
return &SettingModel{}
|
return &SettingModel{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ActivityModel struct {
|
||||||
|
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"ID"`
|
||||||
|
CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"创建时间" scenarios:"search;search;view;export"`
|
||||||
|
Uid string `json:"uid" yaml:"uid" xml:"uid" gorm:"index;size:20" comment:"用户" format:"user" props:"readonly:update" rule:"required"`
|
||||||
|
Action string `json:"action" yaml:"action" xml:"action" gorm:"index;size:20;not null;default:''" comment:"行为" scenarios:"search;list;create;update;view;export" props:"match:exactly" enum:"create:新建#198754;update:更新#f09d00;delete:删除#e63757"`
|
||||||
|
Module string `json:"module" yaml:"module" xml:"module" gorm:"size:60;not null;default:''" comment:"模块" scenarios:"search;list;create;update;view;export"`
|
||||||
|
Table string `json:"table" yaml:"table" xml:"table" gorm:"size:60;not null;default:''" comment:"数据" scenarios:"list;create;update;view;export"`
|
||||||
|
Data string `json:"data" yaml:"data" xml:"data" gorm:"size:10240;not null;default:''" comment:"内容" scenarios:"list;create;update;view;export"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ActivityModel) TableName() string {
|
||||||
|
return "activities"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ActivityModel) FromValue(x *Activity) {
|
||||||
|
m.Id = x.Id
|
||||||
|
m.CreatedAt = x.CreatedAt
|
||||||
|
m.Uid = x.Uid
|
||||||
|
m.Action = x.Action
|
||||||
|
m.Module = x.Module
|
||||||
|
m.Table = x.Table
|
||||||
|
m.Data = x.Data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ActivityModel) ToValue() (x *Activity) {
|
||||||
|
x = &Activity{}
|
||||||
|
x.Id = m.Id
|
||||||
|
x.CreatedAt = m.CreatedAt
|
||||||
|
x.Uid = m.Uid
|
||||||
|
x.Action = m.Action
|
||||||
|
x.Module = m.Module
|
||||||
|
x.Table = m.Table
|
||||||
|
x.Data = m.Data
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ActivityModel) Create(db *gorm.DB) (err error) {
|
||||||
|
return db.Create(m).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ActivityModel) UpdateColumn(db *gorm.DB, column string, value any) (err error) {
|
||||||
|
return db.Model(m).UpdateColumn(column, value).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ActivityModel) Save(db *gorm.DB) (err error) {
|
||||||
|
return db.Save(m).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ActivityModel) Delete(db *gorm.DB) (err error) {
|
||||||
|
return db.Delete(m).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ActivityModel) Find(db *gorm.DB, pk any) (err error) {
|
||||||
|
return db.Where("data=?", pk).First(m).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ActivityModel) FindOne(db *gorm.DB, query any, args ...any) (err error) {
|
||||||
|
return db.Where(query, args...).First(m).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ActivityModel) FindAll(db *gorm.DB, query any, args ...any) (err error) {
|
||||||
|
return db.Where(query, args...).Find(m).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewActivityModel() *ActivityModel {
|
||||||
|
return &ActivityModel{}
|
||||||
|
}
|
||||||
|
|
17
server.go
17
server.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
httpkg "net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -14,6 +15,7 @@ import (
|
||||||
"git.nobla.cn/golang/aeus-admin/models"
|
"git.nobla.cn/golang/aeus-admin/models"
|
||||||
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
|
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
|
||||||
adminTypes "git.nobla.cn/golang/aeus-admin/types"
|
adminTypes "git.nobla.cn/golang/aeus-admin/types"
|
||||||
|
"git.nobla.cn/golang/aeus/middleware/auth"
|
||||||
"git.nobla.cn/golang/aeus/pkg/errors"
|
"git.nobla.cn/golang/aeus/pkg/errors"
|
||||||
"git.nobla.cn/golang/aeus/pkg/pool"
|
"git.nobla.cn/golang/aeus/pkg/pool"
|
||||||
"git.nobla.cn/golang/aeus/transport/http"
|
"git.nobla.cn/golang/aeus/transport/http"
|
||||||
|
@ -35,6 +37,7 @@ func getModels() []any {
|
||||||
&models.Permission{},
|
&models.Permission{},
|
||||||
&models.RolePermission{},
|
&models.RolePermission{},
|
||||||
&models.Setting{},
|
&models.Setting{},
|
||||||
|
&models.Activity{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,6 +210,19 @@ func generateVueFile(prefix string, apiPrefix string, mv *rest.Model) (err error
|
||||||
return os.WriteFile(filename, writer.Bytes(), 0644)
|
return os.WriteFile(filename, writer.Bytes(), 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// restValueLookup 特殊字段获取方式
|
||||||
|
func restValueLookup(column string, w httpkg.ResponseWriter, r *httpkg.Request) string {
|
||||||
|
switch column {
|
||||||
|
case "user":
|
||||||
|
// 从授权信息里面获取用户的ID
|
||||||
|
if t, ok := auth.FromContext(r.Context()); ok {
|
||||||
|
uid, _ := t.GetSubject()
|
||||||
|
return uid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r.Header.Get(column)
|
||||||
|
}
|
||||||
|
|
||||||
// initREST 初始化REST模块
|
// initREST 初始化REST模块
|
||||||
func initREST(ctx context.Context, o *options) (err error) {
|
func initREST(ctx context.Context, o *options) (err error) {
|
||||||
tx := o.db
|
tx := o.db
|
||||||
|
@ -216,6 +232,7 @@ func initREST(ctx context.Context, o *options) (err error) {
|
||||||
opts := make([]rest.Option, 0)
|
opts := make([]rest.Option, 0)
|
||||||
opts = append(opts, o.restOpts...)
|
opts = append(opts, o.restOpts...)
|
||||||
opts = append(opts, rest.WithDB(tx))
|
opts = append(opts, rest.WithDB(tx))
|
||||||
|
opts = append(opts, rest.WithValueLookup(restValueLookup))
|
||||||
if o.apiPrefix != "" {
|
if o.apiPrefix != "" {
|
||||||
opts = append(opts, rest.WithUriPrefix(o.apiPrefix))
|
opts = append(opts, rest.WithUriPrefix(o.apiPrefix))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue