129 lines
3.2 KiB
Go
129 lines
3.2 KiB
Go
// Package processlog 提供交易过程的追加式留痕能力。
|
|
package processlog
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"hfb_sys/backend/internal/model"
|
|
|
|
"gorm.io/datatypes"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
const (
|
|
ActorUser = "user"
|
|
ActorAdmin = "admin"
|
|
ActorSystem = "system"
|
|
)
|
|
|
|
type Entry struct {
|
|
BusinessType string
|
|
BusinessID uint64
|
|
Stage string
|
|
Action string
|
|
ActorType string
|
|
ActorID uint64
|
|
TargetType string
|
|
TargetID *uint64
|
|
Content string
|
|
Reason string
|
|
Payload map[string]any
|
|
Attachments []string
|
|
StateBefore map[string]any
|
|
StateAfter map[string]any
|
|
}
|
|
|
|
func Append(tx *gorm.DB, entry Entry) error {
|
|
actorName, err := displayName(tx, entry.ActorType, entry.ActorID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
targetName := ""
|
|
if entry.TargetID != nil && *entry.TargetID > 0 {
|
|
targetName, err = displayName(tx, entry.TargetType, *entry.TargetID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return tx.Create(&model.ProcessEvent{
|
|
BusinessType: entry.BusinessType,
|
|
BusinessID: entry.BusinessID,
|
|
Stage: entry.Stage,
|
|
Action: entry.Action,
|
|
ActorType: entry.ActorType,
|
|
ActorID: entry.ActorID,
|
|
ActorName: actorName,
|
|
TargetType: entry.TargetType,
|
|
TargetID: entry.TargetID,
|
|
TargetName: targetName,
|
|
Content: strings.TrimSpace(entry.Content),
|
|
Reason: strings.TrimSpace(entry.Reason),
|
|
Payload: jsonValue(entry.Payload),
|
|
AttachmentURLs: jsonValue(entry.Attachments),
|
|
StateBefore: jsonValue(entry.StateBefore),
|
|
StateAfter: jsonValue(entry.StateAfter),
|
|
}).Error
|
|
}
|
|
|
|
func List(tx *gorm.DB, businessType string, businessID uint64) ([]model.ProcessEvent, error) {
|
|
var rows []model.ProcessEvent
|
|
err := tx.Where("business_type = ? AND business_id = ?", businessType, businessID).
|
|
Order("id ASC").Find(&rows).Error
|
|
return rows, err
|
|
}
|
|
|
|
func displayName(tx *gorm.DB, actorType string, id uint64) (string, error) {
|
|
if id == 0 || actorType == ActorSystem {
|
|
return "系统", nil
|
|
}
|
|
switch actorType {
|
|
case ActorAdmin:
|
|
var row model.AdminUser
|
|
if err := tx.Select("id", "username", "nickname").First(&row, id).Error; err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
return "客服 ID " + formatID(id), nil
|
|
}
|
|
return "", err
|
|
}
|
|
if strings.TrimSpace(row.Nickname) != "" {
|
|
return row.Nickname + "(客服)", nil
|
|
}
|
|
if strings.TrimSpace(row.Username) != "" {
|
|
return row.Username + "(客服)", nil
|
|
}
|
|
return "客服 ID " + formatID(id), nil
|
|
default:
|
|
var row model.User
|
|
if err := tx.Select("id", "nickname", "phone").First(&row, id).Error; err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
return "用户 ID " + formatID(id), nil
|
|
}
|
|
return "", err
|
|
}
|
|
if strings.TrimSpace(row.Nickname) != "" {
|
|
return row.Nickname + "(用户)", nil
|
|
}
|
|
if strings.TrimSpace(row.Phone) != "" {
|
|
return row.Phone + "(用户)", nil
|
|
}
|
|
return "用户 ID " + formatID(id), nil
|
|
}
|
|
}
|
|
|
|
func jsonValue(value any) datatypes.JSON {
|
|
if value == nil {
|
|
return datatypes.JSON([]byte("{}"))
|
|
}
|
|
raw, err := json.Marshal(value)
|
|
if err != nil || len(raw) == 0 {
|
|
return datatypes.JSON([]byte("{}"))
|
|
}
|
|
return datatypes.JSON(raw)
|
|
}
|
|
|
|
func formatID(id uint64) string {
|
|
return strconv.FormatUint(id, 10)
|
|
}
|