package logic import ( "context" "easygoadmin/api/v1" "easygoadmin/internal/dao" "easygoadmin/internal/middleware" "easygoadmin/internal/service" ) // ============================== 操作日志业务实现 ============================== // sOperLog 操作日志业务实现 // 实现 service.IOperLog 接口,承载操作日志模块的业务逻辑 type sOperLog struct{} // operLogSerializeMaps 枚举字段到字典编码的映射 // {field}Text 由 dict_item 解析,字典管理页可修改文案 var operLogSerializeMaps = map[string]string{ "source": "operation_log_source", "status": "operation_log_status", } // operLogSpec 操作日志模块声明 var operLogSpec = ModuleSpec[v1.OperLogItem, v1.OperLogItem, v1.OperLogDetailRes]{ Model: dao.OperationLog.Ctx, LikeFields: []string{"title", "url"}, EqFields: []string{"type", "status"}, OrderBy: "id DESC", SerializeMaps: operLogSerializeMaps, // typeText 走静态映射(注解常量值,与字典体系无关) AfterPageList: func(ctx context.Context, list []*v1.OperLogItem, req any) error { for _, item := range list { item.TypeText = LogTypeText(item.Type) } return nil }, AfterDetail: func(ctx context.Context, item *v1.OperLogDetailRes, req any) error { item.TypeText = LogTypeText(item.Type) return nil }, } func init() { service.RegisterOperLog(&sOperLog{}) // 操作日志中间件落库接线(异步批量,见 middleware/operation_log.go) middleware.SetLogSink(SaveOperationLog) } // SaveOperationLog 操作日志落库 // // 作为 LogSink 实现,ctx 为后台上下文 func SaveOperationLog(ctx context.Context, entry *middleware.OperationLogEntry) error { _, err := dao.OperationLog.Ctx(ctx).Data(map[string]any{ "title": entry.Title, "type": entry.Type, "source": entry.Source, "method": entry.Method, "request_method": entry.RequestMethod, "url": entry.URL, "param": entry.Param, "result": entry.Result, "ip": entry.IP, "location": entry.Location, "os": entry.OS, "browser": entry.Browser, "consume_time": entry.ConsumeTime, "status": entry.Status, "error": entry.Error, "create_user": entry.CreateUser, }).Insert() return err } // Page 操作日志分页 // 按查询条件分页返回操作日志列表 func (s *sOperLog) Page(ctx context.Context, req *v1.OperLogPageReq) (res *v1.OperLogPageRes, err error) { list, total, err := operLogSpec.Page(ctx, req, req.GetPageNo(), req.GetPageSize()) if err != nil { return nil, err } return v1.NewPageData(req.GetPageNo(), req.GetPageSize(), total, derefSlice(list)), nil } // List 操作日志全量列表 // 按关键词、类型、状态等条件返回操作日志列表,并补全类型文本 func (s *sOperLog) List(ctx context.Context, req *v1.OperLogListReq) (res v1.OperLogListRes, err error) { list, err := operLogSpec.List(ctx, req) if err != nil { return nil, err } for _, item := range list { item.TypeText = LogTypeText(item.Type) } return derefSlice(list), nil } // Detail 操作日志详情 // 按日志ID查询详情 func (s *sOperLog) Detail(ctx context.Context, req *v1.OperLogDetailReq) (res *v1.OperLogDetailRes, err error) { return operLogSpec.Detail(ctx, req.Id, req) } // Delete 删除操作日志 // 按日志ID删除单条记录 func (s *sOperLog) Delete(ctx context.Context, req *v1.OperLogDeleteReq) (res *v1.OperLogDeleteRes, err error) { if err = operLogSpec.Delete(ctx, req.Id); err != nil { return nil, err } return &v1.OperLogDeleteRes{}, nil } // BatchDelete 批量删除操作日志 // 按日志ID列表批量删除记录 func (s *sOperLog) BatchDelete(ctx context.Context, req *v1.OperLogBatchDeleteReq) (res *v1.OperLogBatchDeleteRes, err error) { if err = operLogSpec.BatchDelete(ctx, req.Ids); err != nil { return nil, err } return &v1.OperLogBatchDeleteRes{}, nil }