同步历史版本代码

This commit is contained in:
2026-03-03 09:32:22 -08:00
parent 7d46b31866
commit 4d8516b2e1
140 changed files with 8399 additions and 489 deletions
@@ -0,0 +1,49 @@
package log
import (
"context"
"strconv"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/logger"
)
type GetErrorLogMessageDetailLogic struct {
logger.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetErrorLogMessageDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetErrorLogMessageDetailLogic {
return &GetErrorLogMessageDetailLogic{ Logger: logger.WithContext(ctx), ctx: ctx, svcCtx: svcCtx }
}
func (l *GetErrorLogMessageDetailLogic) GetErrorLogMessageDetail(idStr string) (resp *types.GetErrorLogMessageDetailResponse, err error) {
if idStr == "" { return &types.GetErrorLogMessageDetailResponse{}, nil }
id, _ := strconv.ParseInt(idStr, 10, 64)
row, err := l.svcCtx.LogMessageModel.FindOne(l.ctx, id)
if err != nil { return nil, err }
var uid int64
if row.UserId != nil { uid = *row.UserId }
var occurred int64
if row.OccurredAt != nil { occurred = row.OccurredAt.UnixMilli() }
return &types.GetErrorLogMessageDetailResponse{
Id: row.Id,
Platform: row.Platform,
AppVersion: row.AppVersion,
OsName: row.OsName,
OsVersion: row.OsVersion,
DeviceId: row.DeviceId,
UserId: uid,
SessionId: row.SessionId,
Level: row.Level,
ErrorCode: row.ErrorCode,
Message: row.Message,
Stack: row.Stack,
ClientIP: row.ClientIP,
UserAgent: row.UserAgent,
Locale: row.Locale,
OccurredAt: occurred,
CreatedAt: row.CreatedAt.UnixMilli(),
}, nil
}
@@ -0,0 +1,59 @@
package log
import (
"context"
"time"
logmessage "github.com/perfect-panel/server/internal/model/logmessage"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/logger"
)
type GetErrorLogMessageListLogic struct {
logger.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetErrorLogMessageListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetErrorLogMessageListLogic {
return &GetErrorLogMessageListLogic{ Logger: logger.WithContext(ctx), ctx: ctx, svcCtx: svcCtx }
}
func (l *GetErrorLogMessageListLogic) GetErrorLogMessageList(req *types.GetErrorLogMessageListRequest) (resp *types.GetErrorLogMessageListResponse, err error) {
var start, end time.Time
if req.Start > 0 { start = time.UnixMilli(req.Start) }
if req.End > 0 { end = time.UnixMilli(req.End) }
rows, total, err := l.svcCtx.LogMessageModel.Filter(l.ctx, &logmessage.FilterParams{
Page: req.Page,
Size: req.Size,
Platform: req.Platform,
Level: req.Level,
UserID: req.UserId,
DeviceID: req.DeviceId,
ErrorCode: req.ErrorCode,
Keyword: req.Keyword,
Start: start,
End: end,
})
if err != nil { return nil, err }
list := make([]types.ErrorLogMessage, 0, len(rows))
for _, r := range rows {
var uid int64
if r.UserId != nil { uid = *r.UserId }
list = append(list, types.ErrorLogMessage{
Id: r.Id,
Platform: r.Platform,
AppVersion: r.AppVersion,
OsName: r.OsName,
OsVersion: r.OsVersion,
DeviceId: r.DeviceId,
UserId: uid,
SessionId: r.SessionId,
Level: r.Level,
ErrorCode: r.ErrorCode,
Message: r.Message,
CreatedAt: r.CreatedAt.UnixMilli(),
})
}
return &types.GetErrorLogMessageListResponse{ Total: total, List: list }, nil
}
@@ -131,6 +131,8 @@ func parsePaymentPlatformConfig(ctx context.Context, platform payment.Platform,
return handleConfig("Epay", &paymentModel.EPayConfig{})
case payment.CryptoSaaS:
return handleConfig("CryptoSaaS", &paymentModel.CryptoSaaSConfig{})
case payment.AppleIAP:
return handleConfig("AppleIAP", &paymentModel.AppleIAPConfig{})
default:
return ""
}
@@ -4,6 +4,7 @@ import (
"context"
"reflect"
"github.com/perfect-panel/server/initialize"
"github.com/perfect-panel/server/internal/config"
"github.com/perfect-panel/server/internal/model/system"
@@ -56,5 +57,6 @@ func (l *UpdateVerifyCodeConfigLogic) UpdateVerifyCodeConfig(req *types.VerifyCo
l.Errorw("[UpdateRegisterConfig] update verify code config error", logger.Field("error", err.Error()))
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update register config error: %v", err.Error())
}
initialize.Verify(l.svcCtx)
return nil
}
@@ -40,12 +40,41 @@ func (l *GetUserListLogic) GetUserList(req *types.GetUserListRequest) (*types.Ge
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "GetUserListLogic failed: %v", err.Error())
}
// Batch fetch active subscriptions
userIds := make([]int64, 0, len(list))
for _, u := range list {
userIds = append(userIds, u.Id)
}
activeSubs, err := l.svcCtx.UserModel.FindActiveSubscribesByUserIds(l.ctx, userIds)
if err != nil {
// Log error but continue
l.Logger.Error("FindActiveSubscribesByUserIds failed", logger.Field("error", err.Error()))
}
userRespList := make([]types.User, 0, len(list))
for _, item := range list {
var u types.User
tool.DeepCopy(&u, item)
// Set LastLoginTime
if item.LastLoginTime != nil {
u.LastLoginTime = item.LastLoginTime.Unix()
}
// Set MemberStatus and update LastLoginTime from traffic
if activeSubs != nil {
if info, ok := activeSubs[item.Id]; ok {
u.MemberStatus = info.MemberStatus
if info.LastTrafficAt != nil {
trafficTime := info.LastTrafficAt.Unix()
if trafficTime > u.LastLoginTime {
u.LastLoginTime = trafficTime
}
}
}
}
// 处理 AuthMethods
authMethods := make([]types.UserAuthMethod, len(u.AuthMethods)) // 直接创建目标 slice
for i, method := range u.AuthMethods {
@@ -13,6 +13,7 @@ import (
"github.com/perfect-panel/server/pkg/tool"
"github.com/perfect-panel/server/pkg/xerr"
"github.com/pkg/errors"
"gorm.io/gorm"
)
type UpdateUserBasicInfoLogic struct {
@@ -43,98 +44,106 @@ func (l *UpdateUserBasicInfoLogic) UpdateUserBasicInfo(req *types.UpdateUserBasi
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "Invalid Image Size")
}
if userInfo.Balance != req.Balance {
change := req.Balance - userInfo.Balance
balanceLog := log.Balance{
Type: log.BalanceTypeAdjust,
Amount: change,
OrderNo: "",
Balance: req.Balance,
Timestamp: time.Now().UnixMilli(),
}
content, _ := balanceLog.Marshal()
err = l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
Type: log.TypeBalance.Uint8(),
Date: time.Now().Format(time.DateOnly),
ObjectID: userInfo.Id,
Content: string(content),
})
if err != nil {
l.Errorw("[UpdateUserBasicInfoLogic] Insert Balance Log Error:", logger.Field("err", err.Error()), logger.Field("userId", req.UserId))
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "Insert Balance Log Error")
}
userInfo.Balance = req.Balance
}
if userInfo.GiftAmount != req.GiftAmount {
change := req.GiftAmount - userInfo.GiftAmount
if change != 0 {
var changeType uint16
if userInfo.GiftAmount < req.GiftAmount {
changeType = log.GiftTypeIncrease
} else {
changeType = log.GiftTypeReduce
}
giftLog := log.Gift{
Type: changeType,
err = l.svcCtx.UserModel.Transaction(l.ctx, func(tx *gorm.DB) error {
if userInfo.Balance != req.Balance {
change := req.Balance - userInfo.Balance
balanceLog := log.Balance{
Type: log.BalanceTypeAdjust,
Amount: change,
Balance: req.GiftAmount,
Remark: "Admin adjustment",
OrderNo: "",
Balance: req.Balance,
Timestamp: time.Now().UnixMilli(),
}
content, _ := giftLog.Marshal()
// Add gift amount change log
err = l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
Type: log.TypeGift.Uint8(),
content, _ := balanceLog.Marshal()
err = tx.Create(&log.SystemLog{
Type: log.TypeBalance.Uint8(),
Date: time.Now().Format(time.DateOnly),
ObjectID: userInfo.Id,
Content: string(content),
})
}).Error
if err != nil {
l.Errorw("[UpdateUserBasicInfoLogic] Insert Balance Log Error:", logger.Field("err", err.Error()), logger.Field("userId", req.UserId))
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "Insert Balance Log Error")
return err
}
userInfo.GiftAmount = req.GiftAmount
}
}
if req.Commission != userInfo.Commission {
commentLog := log.Commission{
Type: log.CommissionTypeAdjust,
Amount: req.Commission - userInfo.Commission,
Timestamp: time.Now().UnixMilli(),
userInfo.Balance = req.Balance
}
content, _ := commentLog.Marshal()
err = l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
Type: log.TypeCommission.Uint8(),
Date: time.Now().Format(time.DateOnly),
ObjectID: userInfo.Id,
Content: string(content),
})
if userInfo.GiftAmount != req.GiftAmount {
change := req.GiftAmount - userInfo.GiftAmount
if change != 0 {
var changeType uint16
if userInfo.GiftAmount < req.GiftAmount {
changeType = log.GiftTypeIncrease
} else {
changeType = log.GiftTypeReduce
}
giftLog := log.Gift{
Type: changeType,
Amount: change,
Balance: req.GiftAmount,
Remark: "Admin adjustment",
Timestamp: time.Now().UnixMilli(),
}
content, _ := giftLog.Marshal()
// Add gift amount change log
err = tx.Create(&log.SystemLog{
Type: log.TypeGift.Uint8(),
Date: time.Now().Format(time.DateOnly),
ObjectID: userInfo.Id,
Content: string(content),
}).Error
if err != nil {
return err
}
userInfo.GiftAmount = req.GiftAmount
}
}
if req.Commission != userInfo.Commission {
commentLog := log.Commission{
Type: log.CommissionTypeAdjust,
Amount: req.Commission - userInfo.Commission,
Timestamp: time.Now().UnixMilli(),
}
content, _ := commentLog.Marshal()
err = tx.Create(&log.SystemLog{
Type: log.TypeCommission.Uint8(),
Date: time.Now().Format(time.DateOnly),
ObjectID: userInfo.Id,
Content: string(content),
}).Error
if err != nil {
return err
}
userInfo.Commission = req.Commission
}
tool.DeepCopy(userInfo, req)
userInfo.OnlyFirstPurchase = &req.OnlyFirstPurchase
userInfo.ReferralPercentage = req.ReferralPercentage
if req.Password != "" {
if userInfo.Id == 2 && isDemo {
return errors.New("Demo mode does not allow modification of the admin user password")
}
userInfo.Password = tool.EncodePassWord(req.Password)
userInfo.Algo = "default"
}
err = l.svcCtx.UserModel.Update(l.ctx, userInfo, tx)
if err != nil {
l.Errorw("[UpdateUserBasicInfoLogic] Insert Commission Log Error:", logger.Field("err", err.Error()), logger.Field("userId", req.UserId))
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "Insert Commission Log Error")
return err
}
userInfo.Commission = req.Commission
}
tool.DeepCopy(userInfo, req)
userInfo.OnlyFirstPurchase = &req.OnlyFirstPurchase
userInfo.ReferralPercentage = req.ReferralPercentage
if req.Password != "" {
if userInfo.Id == 2 && isDemo {
return errors.Wrapf(xerr.NewErrCodeMsg(503, "Demo mode does not allow modification of the admin user password"), "UpdateUserBasicInfo failed: cannot update admin user password in demo mode")
}
userInfo.Password = tool.EncodePassWord(req.Password)
userInfo.Algo = "default"
}
return nil
})
err = l.svcCtx.UserModel.Update(l.ctx, userInfo)
if err != nil {
l.Errorw("[UpdateUserBasicInfoLogic] Update User Error:", logger.Field("err", err.Error()), logger.Field("userId", req.UserId))
if err.Error() == "Demo mode does not allow modification of the admin user password" {
return errors.Wrapf(xerr.NewErrCodeMsg(503, "Demo mode does not allow modification of the admin user password"), "UpdateUserBasicInfo failed: cannot update admin user password in demo mode")
}
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "Update User Error")
}