- Service 层:energy_service → energize/operations/admin/query 四文件 - Service 层:post_service → helpers/audit + 核心 CRUD 保留 - Service 层:favorite_service → items + 核心文件夹操作保留 - Service 层:auth_service → password + 核心注册/登录保留 - Service 层:notification_service → notify + 核心列表/已读保留 - Service 层:audit_service → review + 核心列表/详情保留 - Controller 层:studio_controller → page/write/api/post_api/action 五文件 - Controller 层:post_controller → page/api/upload 三文件 - Controller 层:comment_controller → list/write/action/upload 四文件 - 清理未使用导入(notification_service.go 移除 fmt)
93 lines
2.6 KiB
Go
93 lines
2.6 KiB
Go
package service
|
||
|
||
import (
|
||
"fmt"
|
||
|
||
"metazone.cc/metalab/internal/common"
|
||
"metazone.cc/metalab/internal/model"
|
||
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// AdminAdjust 后台调整用户域能
|
||
// mode: "admin_transfer"(受公户余额约束)| "system_operation"(不受约束,不碰公户)
|
||
func (s *EnergyService) AdminAdjust(operatorUID uint, userIDs []uint, amount int, description string, mode string) error {
|
||
if mode == "" {
|
||
mode = model.FundTypeAdminTransfer
|
||
}
|
||
|
||
return s.db.Transaction(func(tx *gorm.DB) error {
|
||
txRepo := s.repo.WithTx(tx)
|
||
|
||
// admin_transfer:公户出账需检查余额(行锁防 TOCTOU 竞态)
|
||
isAdminTransfer := mode == model.FundTypeAdminTransfer
|
||
if isAdminTransfer && amount > 0 && s.fundRepo != nil {
|
||
txFundRepo := s.fundRepo.WithTx(tx)
|
||
totalCost := amount * len(userIDs)
|
||
balance, err := txFundRepo.LockAndGetBalance()
|
||
if err != nil {
|
||
return fmt.Errorf("查询公户余额失败: %w", err)
|
||
}
|
||
if balance < totalCost {
|
||
return common.ErrInsufficientFund
|
||
}
|
||
}
|
||
|
||
for _, uid := range userIDs {
|
||
if err := txRepo.AddEnergy(uid, amount); err != nil {
|
||
return fmt.Errorf("调整用户 %d 域能失败: %w", uid, err)
|
||
}
|
||
|
||
opUID := operatorUID
|
||
energyLog := &model.EnergyLog{
|
||
UserID: uid,
|
||
Amount: amount,
|
||
Type: model.EnergyTypeAdminAdjust,
|
||
Description: description,
|
||
OperatorUID: &opUID,
|
||
}
|
||
if err := txRepo.CreateEnergyLog(energyLog); err != nil {
|
||
return fmt.Errorf("创建调整流水失败: %w", err)
|
||
}
|
||
}
|
||
|
||
// admin_transfer:公户扣款 + 公户流水(system_operation 不碰公户)
|
||
if isAdminTransfer && s.fundRepo != nil {
|
||
txFundRepo := s.fundRepo.WithTx(tx)
|
||
totalCost := amount * len(userIDs)
|
||
if err := txFundRepo.IncrBalance(-totalCost); err != nil {
|
||
return fmt.Errorf("公户余额调整失败: %w", err)
|
||
}
|
||
|
||
totalDisplay := float64(totalCost) / 10
|
||
fundLog := &model.FundLog{
|
||
Amount: -totalCost,
|
||
Type: mode,
|
||
OperatorUID: &operatorUID,
|
||
Description: fmt.Sprintf("%s:调整 %d 名用户域能 %.1f,说明:%s", getFundModeName(mode), len(userIDs), totalDisplay, description),
|
||
}
|
||
if len(userIDs) > 0 {
|
||
fundLog.RelatedType = "user"
|
||
fundLog.RelatedID = userIDs[0]
|
||
}
|
||
if err := txFundRepo.CreateLog(fundLog); err != nil {
|
||
return fmt.Errorf("创建公户流水失败: %w", err)
|
||
}
|
||
}
|
||
|
||
return nil
|
||
})
|
||
}
|
||
|
||
// getFundModeName 返回操作模式中文名
|
||
func getFundModeName(mode string) string {
|
||
switch mode {
|
||
case model.FundTypeAdminTransfer:
|
||
return "管理转出"
|
||
case model.FundTypeSystemOperation:
|
||
return "系统操作"
|
||
default:
|
||
return "后台调整"
|
||
}
|
||
}
|