common增加通用log模块
This commit is contained in:
9
beans/beans.go
Normal file
9
beans/beans.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package beans
|
||||||
|
|
||||||
|
type ResponseEmpty struct {
|
||||||
|
}
|
||||||
|
type Page struct {
|
||||||
|
PageNum int `p:"pageNum"` //当前页码
|
||||||
|
PageSize int `p:"pageSize"` //每页数
|
||||||
|
Total int //总页数
|
||||||
|
}
|
||||||
15
log/consts/log_const.go
Normal file
15
log/consts/log_const.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package consts
|
||||||
|
|
||||||
|
// OperationType 操作类型常量
|
||||||
|
type OperationType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
OperationCreate OperationType = "create" // 创建
|
||||||
|
OperationUpdate OperationType = "update" // 更新
|
||||||
|
OperationDelete OperationType = "delete" // 删除
|
||||||
|
)
|
||||||
|
|
||||||
|
// OperationLogCollection 操作日志集合名称常量
|
||||||
|
const (
|
||||||
|
OperationLogCollection = "operation_logs" // 操作日志集合名称
|
||||||
|
)
|
||||||
76
log/controller/log_controller.go
Normal file
76
log/controller/log_controller.go
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"gitee.com/red-future---jilin-g/common/beans"
|
||||||
|
"gitee.com/red-future---jilin-g/common/log/model/dto"
|
||||||
|
"gitee.com/red-future---jilin-g/common/log/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
type operationLog struct{}
|
||||||
|
|
||||||
|
// OperationLog 操作日志控制器
|
||||||
|
var OperationLog = new(operationLog)
|
||||||
|
|
||||||
|
// GetByID 根据ID获取操作日志
|
||||||
|
// @Summary 获取操作日志详情
|
||||||
|
// @Description 根据日志ID获取操作日志的详细信息
|
||||||
|
func (c *operationLog) GetByID(ctx context.Context, req *dto.GetLogReq) (res *dto.GetLogResp, err error) {
|
||||||
|
logInfo, err := service.OperationLog.GetByID(ctx, req.ID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res = &dto.GetLogResp{
|
||||||
|
OperationLogInfo: *logInfo,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// List 查询操作日志列表(通用方法,支持根据不同条件动态查询)
|
||||||
|
// @Summary 查询操作日志列表
|
||||||
|
// @Description 根据多个条件查询操作日志列表
|
||||||
|
func (c *operationLog) List(ctx context.Context, req *dto.ListLogsReq) (res *dto.ListLogsResp, err error) {
|
||||||
|
// 处理排序字段
|
||||||
|
var sortFields []string
|
||||||
|
if req.SortFields != "" {
|
||||||
|
sortFields = strings.Split(req.SortFields, ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
logs, total, err := service.OperationLog.List(ctx, req, sortFields...)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res = &dto.ListLogsResp{
|
||||||
|
Logs: logs,
|
||||||
|
Total: total,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordCreate 记录创建操作日志
|
||||||
|
// @Summary 记录创建操作日志
|
||||||
|
// @Description 记录数据创建操作的行为日志
|
||||||
|
func (c *operationLog) RecordCreate(ctx context.Context, req *dto.RecordCreateLogReq) (res *beans.ResponseEmpty, err error) {
|
||||||
|
err = service.OperationLog.RecordCreate(ctx, req.Module, req.Service, req.Resource, req.ResourceID, req.Description, req.AfterData)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordUpdate 记录更新操作日志
|
||||||
|
// @Summary 记录更新操作日志
|
||||||
|
// @Description 记录数据更新操作的行为日志
|
||||||
|
func (c *operationLog) RecordUpdate(ctx context.Context, req *dto.RecordUpdateLogReq) (res *beans.ResponseEmpty, err error) {
|
||||||
|
err = service.OperationLog.RecordUpdate(ctx, req.Module, req.Service, req.Resource, req.ResourceID, req.Description, req.BeforeData, req.AfterData)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordDelete 记录删除操作日志
|
||||||
|
// @Summary 记录删除操作日志
|
||||||
|
// @Description 记录数据删除操作的行为日志
|
||||||
|
func (c *operationLog) RecordDelete(ctx context.Context, req *dto.RecordDeleteLogReq) (res *beans.ResponseEmpty, err error) {
|
||||||
|
err = service.OperationLog.RecordDelete(ctx, req.Module, req.Service, req.Resource, req.ResourceID, req.Description, req.BeforeData)
|
||||||
|
return
|
||||||
|
}
|
||||||
142
log/dao/log_dao.go
Normal file
142
log/dao/log_dao.go
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
package dao
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gitee.com/red-future---jilin-g/common/log/consts"
|
||||||
|
"gitee.com/red-future---jilin-g/common/log/model/dto"
|
||||||
|
"gitee.com/red-future---jilin-g/common/log/model/entity"
|
||||||
|
"gitee.com/red-future---jilin-g/common/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/v2/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
type log struct{}
|
||||||
|
|
||||||
|
// Log 日志数据访问对象
|
||||||
|
var Log = &log{}
|
||||||
|
|
||||||
|
// Create 创建日志记录
|
||||||
|
func (d *log) Create(ctx context.Context, log *entity.OperationLog) error {
|
||||||
|
_, err := mongo.DB().Insert(ctx, []interface{}{log}, consts.OperationLogCollection)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateBatch 批量创建日志记录
|
||||||
|
func (d *log) CreateBatch(ctx context.Context, logs []*entity.OperationLog) error {
|
||||||
|
if len(logs) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
documents := make([]interface{}, len(logs))
|
||||||
|
for i, log := range logs {
|
||||||
|
documents[i] = log
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := mongo.DB().Insert(ctx, documents, consts.OperationLogCollection)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByID 根据ID获取日志
|
||||||
|
func (d *log) GetByID(ctx context.Context, id string) (*entity.OperationLog, error) {
|
||||||
|
objectID, err := bson.ObjectIDFromHex(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
filter := bson.M{"_id": objectID}
|
||||||
|
var log entity.OperationLog
|
||||||
|
err = mongo.DB().FindOne(ctx, filter, &log, consts.OperationLogCollection)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &log, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// List 查询日志列表(通用方法,通过filter动态拼接查询条件)
|
||||||
|
func (d *log) List(ctx context.Context, filter *dto.ListLogsReq, sortFields ...string) ([]*entity.OperationLog, int64, error) {
|
||||||
|
bsonFilter := buildFilter(filter)
|
||||||
|
|
||||||
|
total, err := mongo.DB().Count(ctx, bsonFilter, consts.OperationLogCollection)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var findOptions []options.Lister[options.FindOptions]
|
||||||
|
if filter.PageNum > 0 && filter.PageSize > 0 {
|
||||||
|
findOptions = append(findOptions, options.Find().SetSkip(int64((filter.PageNum-1)*filter.PageSize)).SetLimit(int64(filter.PageSize)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(sortFields) > 0 {
|
||||||
|
sort := bson.D{}
|
||||||
|
for _, field := range sortFields {
|
||||||
|
var order int
|
||||||
|
if len(field) > 0 && field[0] == '-' {
|
||||||
|
order = -1
|
||||||
|
field = field[1:]
|
||||||
|
} else {
|
||||||
|
order = 1
|
||||||
|
}
|
||||||
|
sort = append(sort, bson.E{Key: field, Value: order})
|
||||||
|
}
|
||||||
|
findOptions = append(findOptions, options.Find().SetSort(sort))
|
||||||
|
} else {
|
||||||
|
findOptions = append(findOptions, options.Find().SetSort(bson.D{{Key: "createdAt", Value: -1}}))
|
||||||
|
}
|
||||||
|
|
||||||
|
var logs []*entity.OperationLog
|
||||||
|
err = mongo.DB().Find(ctx, bsonFilter, &logs, consts.OperationLogCollection, findOptions...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return logs, total, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildFilter 构建MongoDB查询过滤器
|
||||||
|
func buildFilter(filter interface{}) bson.M {
|
||||||
|
bsonFilter := make(bson.M)
|
||||||
|
|
||||||
|
// 从ListLogsReq结构体中提取字段值
|
||||||
|
if req, ok := filter.(*dto.ListLogsReq); ok {
|
||||||
|
if req.Module != "" {
|
||||||
|
bsonFilter["module"] = req.Module
|
||||||
|
}
|
||||||
|
if req.Service != "" {
|
||||||
|
bsonFilter["service"] = req.Service
|
||||||
|
}
|
||||||
|
if req.Operation != "" {
|
||||||
|
bsonFilter["operation"] = req.Operation
|
||||||
|
}
|
||||||
|
if req.Resource != "" {
|
||||||
|
bsonFilter["resource"] = req.Resource
|
||||||
|
}
|
||||||
|
if req.ResourceID != "" {
|
||||||
|
bsonFilter["resource_id"] = req.ResourceID
|
||||||
|
}
|
||||||
|
if req.UserID != "" {
|
||||||
|
bsonFilter["user_id"] = req.UserID
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理时间范围字段
|
||||||
|
if req.StartTime != "" || req.EndTime != "" {
|
||||||
|
timeFilter := bson.M{}
|
||||||
|
if req.StartTime != "" {
|
||||||
|
if startTime, err := time.Parse("2006-01-02 15:04:05", req.StartTime); err == nil {
|
||||||
|
timeFilter["$gte"] = startTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if req.EndTime != "" {
|
||||||
|
if endTime, err := time.Parse("2006-01-02 15:04:05", req.EndTime); err == nil {
|
||||||
|
timeFilter["$lte"] = endTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(timeFilter) > 0 {
|
||||||
|
bsonFilter["createdAt"] = timeFilter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bsonFilter
|
||||||
|
}
|
||||||
96
log/model/dto/log_dto.go
Normal file
96
log/model/dto/log_dto.go
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
package dto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gitee.com/red-future---jilin-g/common/beans"
|
||||||
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ========== 操作日志查询相关DTO ==========
|
||||||
|
|
||||||
|
// GetLogReq 获取操作日志请求
|
||||||
|
type GetLogReq struct {
|
||||||
|
g.Meta `path:"/getLog" method:"get" tags:"操作日志" summary:"获取操作日志详情" dc:"根据日志ID获取操作日志的详细信息"`
|
||||||
|
ID string `json:"id" v:"required" dc:"日志ID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLogResp 获取操作日志响应
|
||||||
|
type GetLogResp struct {
|
||||||
|
OperationLogInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// OperationLogInfo 操作日志信息
|
||||||
|
type OperationLogInfo struct {
|
||||||
|
ID string `json:"id" dc:"日志ID"`
|
||||||
|
Module string `json:"module" dc:"模块名"`
|
||||||
|
Service string `json:"service" dc:"服务名"`
|
||||||
|
Operation string `json:"operation" dc:"操作类型"`
|
||||||
|
Resource string `json:"resource" dc:"资源类型"`
|
||||||
|
ResourceID string `json:"resource_id" dc:"资源ID"`
|
||||||
|
UserID interface{} `json:"user_id" dc:"操作人ID"`
|
||||||
|
UserName string `json:"user_name" dc:"操作人名称"`
|
||||||
|
IPAddress string `json:"ip_address" dc:"操作IP地址"`
|
||||||
|
UserAgent string `json:"user_agent" dc:"用户代理"`
|
||||||
|
Description string `json:"description" dc:"操作描述"`
|
||||||
|
BeforeData map[string]interface{} `json:"before_data" dc:"操作前的数据"`
|
||||||
|
AfterData map[string]interface{} `json:"after_data" dc:"操作后的数据"`
|
||||||
|
ExtraData map[string]interface{} `json:"extra_data" dc:"额外数据"`
|
||||||
|
CreatedAt string `json:"created_at" dc:"创建时间"`
|
||||||
|
UpdatedAt string `json:"updated_at" dc:"更新时间"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListLogsReq 查询操作日志列表请求(通用方法,支持根据不同条件动态查询)
|
||||||
|
type ListLogsReq struct {
|
||||||
|
g.Meta `path:"/listLogs" method:"get" tags:"操作日志" summary:"查询操作日志列表" dc:"根据多个条件查询操作日志列表"`
|
||||||
|
beans.Page
|
||||||
|
Module string `json:"module" dc:"模块名(可选)"`
|
||||||
|
Service string `json:"service" dc:"服务名(可选)"`
|
||||||
|
Operation string `json:"operation" dc:"操作类型(可选)"`
|
||||||
|
Resource string `json:"resource" dc:"资源类型(可选)"`
|
||||||
|
ResourceID string `json:"resource_id" dc:"资源ID(可选)"`
|
||||||
|
UserID string `json:"user_id" dc:"用户ID(可选)"`
|
||||||
|
StartTime string `json:"start_time" dc:"开始时间(可选)"`
|
||||||
|
EndTime string `json:"end_time" dc:"结束时间(可选)"`
|
||||||
|
SortFields string `json:"sort_fields" dc:"排序字段,多个用逗号分隔,如:-createdAt,module(可选)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListLogsResp 查询操作日志列表响应
|
||||||
|
type ListLogsResp struct {
|
||||||
|
Logs []OperationLogInfo `json:"logs" dc:"日志列表"`
|
||||||
|
Total int64 `json:"total" dc:"总数"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 记录操作日志DTO ==========
|
||||||
|
|
||||||
|
// RecordCreateLogReq 记录创建操作日志请求
|
||||||
|
type RecordCreateLogReq struct {
|
||||||
|
g.Meta `path:"/recordCreateLog" method:"post" tags:"操作日志" summary:"记录创建操作日志" dc:"记录数据创建操作的行为日志"`
|
||||||
|
Module string `json:"module" v:"required" dc:"模块名"`
|
||||||
|
Service string `json:"service" v:"required" dc:"服务名"`
|
||||||
|
Resource string `json:"resource" v:"required" dc:"资源类型"`
|
||||||
|
ResourceID string `json:"resource_id" v:"required" dc:"资源ID"`
|
||||||
|
Description string `json:"description" dc:"操作描述"`
|
||||||
|
AfterData map[string]interface{} `json:"after_data" dc:"操作后的数据"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordUpdateLogReq 记录更新操作日志请求
|
||||||
|
type RecordUpdateLogReq struct {
|
||||||
|
g.Meta `path:"/recordUpdateLog" method:"post" tags:"操作日志" summary:"记录更新操作日志" dc:"记录数据更新操作的行为日志"`
|
||||||
|
Module string `json:"module" v:"required" dc:"模块名"`
|
||||||
|
Service string `json:"service" v:"required" dc:"服务名"`
|
||||||
|
Resource string `json:"resource" v:"required" dc:"资源类型"`
|
||||||
|
ResourceID string `json:"resource_id" v:"required" dc:"资源ID"`
|
||||||
|
Description string `json:"description" dc:"操作描述"`
|
||||||
|
BeforeData map[string]interface{} `json:"before_data" dc:"操作前的数据"`
|
||||||
|
AfterData map[string]interface{} `json:"after_data" dc:"操作后的数据"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordDeleteLogReq 记录删除操作日志请求
|
||||||
|
type RecordDeleteLogReq struct {
|
||||||
|
g.Meta `path:"/recordDeleteLog" method:"post" tags:"操作日志" summary:"记录删除操作日志" dc:"记录数据删除操作的行为日志"`
|
||||||
|
Module string `json:"module" v:"required" dc:"模块名"`
|
||||||
|
Service string `json:"service" v:"required" dc:"服务名"`
|
||||||
|
Resource string `json:"resource" v:"required" dc:"资源类型"`
|
||||||
|
ResourceID string `json:"resource_id" v:"required" dc:"资源ID"`
|
||||||
|
Description string `json:"description" dc:"操作描述"`
|
||||||
|
BeforeData map[string]interface{} `json:"before_data" dc:"操作前的数据"`
|
||||||
|
}
|
||||||
24
log/model/entity/log.go
Normal file
24
log/model/entity/log.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gitee.com/red-future---jilin-g/common/do"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OperationLog 操作日志实体 - 用于记录数据增删改操作行为
|
||||||
|
type OperationLog struct {
|
||||||
|
do.MongoBaseDO `bson:",inline"`
|
||||||
|
|
||||||
|
Module string `bson:"module" json:"module"` // 模块名:如 order, wallet, market 等
|
||||||
|
Service string `bson:"service" json:"service"` // 服务名:具体的微服务名称
|
||||||
|
Operation string `bson:"operation" json:"operation"` // 操作类型:create, update, delete
|
||||||
|
Resource string `bson:"resource" json:"resource"` // 资源类型:如 order, wallet, product 等
|
||||||
|
ResourceID string `bson:"resource_id" json:"resource_id"` // 资源ID:具体操作的数据ID,如订单号、钱包ID等
|
||||||
|
UserID interface{} `bson:"user_id" json:"user_id"` // 操作人ID
|
||||||
|
UserName string `bson:"user_name" json:"user_name"` // 操作人名称
|
||||||
|
IPAddress string `bson:"ip_address" json:"ip_address"` // 操作IP地址
|
||||||
|
UserAgent string `bson:"user_agent" json:"user_agent"` // 用户代理
|
||||||
|
Description string `bson:"description" json:"description"` // 操作描述
|
||||||
|
BeforeData map[string]interface{} `bson:"before_data,omitempty" json:"before_data"` // 操作前的数据(用于update/delete)
|
||||||
|
AfterData map[string]interface{} `bson:"after_data,omitempty" json:"after_data"` // 操作后的数据(用于create/update)
|
||||||
|
ExtraData map[string]interface{} `bson:"extra_data,omitempty" json:"extra_data"` // 额外数据
|
||||||
|
}
|
||||||
121
log/service/log_service.go
Normal file
121
log/service/log_service.go
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"gitee.com/red-future---jilin-g/common/log/consts"
|
||||||
|
"gitee.com/red-future---jilin-g/common/log/dao"
|
||||||
|
"gitee.com/red-future---jilin-g/common/log/model/dto"
|
||||||
|
logEntity "gitee.com/red-future---jilin-g/common/log/model/entity"
|
||||||
|
"gitee.com/red-future---jilin-g/common/utils"
|
||||||
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
|
"github.com/gogf/gf/v2/os/gtime"
|
||||||
|
"github.com/gogf/gf/v2/util/gconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type operationLog struct{}
|
||||||
|
|
||||||
|
// OperationLog 操作日志服务
|
||||||
|
var OperationLog = &operationLog{}
|
||||||
|
|
||||||
|
// RecordCreate 记录创建操作
|
||||||
|
func (s *operationLog) RecordCreate(ctx context.Context, module, service, resource, resourceID, description string, afterData map[string]interface{}) error {
|
||||||
|
return s.record(ctx, module, service, string(consts.OperationCreate), resource, resourceID, description, nil, afterData, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordUpdate 记录更新操作
|
||||||
|
func (s *operationLog) RecordUpdate(ctx context.Context, module, service, resource, resourceID, description string, beforeData, afterData map[string]interface{}) error {
|
||||||
|
return s.record(ctx, module, service, string(consts.OperationUpdate), resource, resourceID, description, beforeData, afterData, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordDelete 记录删除操作
|
||||||
|
func (s *operationLog) RecordDelete(ctx context.Context, module, service, resource, resourceID, description string, beforeData map[string]interface{}) error {
|
||||||
|
return s.record(ctx, module, service, string(consts.OperationDelete), resource, resourceID, description, beforeData, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BatchRecordCreate 批量记录创建操作
|
||||||
|
func (s *operationLog) BatchRecordCreate(ctx context.Context, logs []*logEntity.OperationLog) error {
|
||||||
|
return dao.Log.CreateBatch(ctx, logs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByID 根据ID获取操作日志
|
||||||
|
func (s *operationLog) GetByID(ctx context.Context, id string) (*dto.OperationLogInfo, error) {
|
||||||
|
log, err := dao.Log.GetByID(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var logInfo dto.OperationLogInfo
|
||||||
|
gconv.Struct(log, &logInfo)
|
||||||
|
logInfo.ID = log.Id.Hex()
|
||||||
|
logInfo.CreatedAt = gtime.New(log.CreatedAt).Format("Y-m-d H:i:s")
|
||||||
|
logInfo.UpdatedAt = gtime.New(log.UpdatedAt).Format("Y-m-d H:i:s")
|
||||||
|
return &logInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// List 查询操作日志列表
|
||||||
|
func (s *operationLog) List(ctx context.Context, filter interface{}, sortFields ...string) ([]dto.OperationLogInfo, int64, error) {
|
||||||
|
logs, total, err := dao.Log.List(ctx, filter, sortFields...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var logInfos []dto.OperationLogInfo
|
||||||
|
err = gconv.Slice(logs, &logInfos)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理特殊字段
|
||||||
|
for i, log := range logs {
|
||||||
|
logInfos[i].ID = log.Id.Hex()
|
||||||
|
logInfos[i].CreatedAt = gtime.New(log.CreatedAt).Format("Y-m-d H:i:s")
|
||||||
|
logInfos[i].UpdatedAt = gtime.New(log.UpdatedAt).Format("Y-m-d H:i:s")
|
||||||
|
}
|
||||||
|
|
||||||
|
return logInfos, total, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// record 记录操作日志的通用方法
|
||||||
|
func (s *operationLog) record(ctx context.Context, module, service, operation, resource, resourceID, description string, beforeData, afterData, extraData map[string]interface{}) error {
|
||||||
|
// 获取用户信息
|
||||||
|
user, err := utils.GetUserInfo(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取请求信息
|
||||||
|
ipAddress, userAgent := getHTTPRequestInfo(ctx)
|
||||||
|
|
||||||
|
var userName string
|
||||||
|
if user.UserName != nil {
|
||||||
|
userName = gconv.String(user.UserName)
|
||||||
|
}
|
||||||
|
|
||||||
|
log := &logEntity.OperationLog{
|
||||||
|
Module: module,
|
||||||
|
Service: service,
|
||||||
|
Operation: operation,
|
||||||
|
Resource: resource,
|
||||||
|
ResourceID: resourceID,
|
||||||
|
UserID: user.UserName,
|
||||||
|
UserName: userName,
|
||||||
|
IPAddress: ipAddress,
|
||||||
|
UserAgent: userAgent,
|
||||||
|
Description: description,
|
||||||
|
BeforeData: beforeData,
|
||||||
|
AfterData: afterData,
|
||||||
|
ExtraData: extraData,
|
||||||
|
}
|
||||||
|
|
||||||
|
return dao.Log.Create(ctx, log)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getHTTPRequestInfo 从上下文中获取HTTP请求信息
|
||||||
|
func getHTTPRequestInfo(ctx context.Context) (ipAddress, userAgent string) {
|
||||||
|
request := g.RequestFromCtx(ctx)
|
||||||
|
if request != nil {
|
||||||
|
return request.GetClientIp(), request.Header.Get("User-Agent")
|
||||||
|
}
|
||||||
|
return "", ""
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user