refactor: 礼物功能,优化用户获取逻辑,优化排行榜逻辑,优化调用逻辑,优化结构。
parent
310a2dcb5c
commit
0e7b79a083
@ -0,0 +1,67 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"git.noahlan.cn/northlan/ntools-go/gorm-zero/gormc"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ GiftModel = (*customGiftModel)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// GiftModel is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in customGiftModel.
|
||||||
|
GiftModel interface {
|
||||||
|
giftModel
|
||||||
|
// Transaction 开启事务,传入方法即可
|
||||||
|
Transaction(ctx context.Context, tx *gorm.DB, fn func(tx *gorm.DB) error) error
|
||||||
|
// InsertTx 事务插入
|
||||||
|
InsertTx(ctx context.Context, tx *gorm.DB, data *Gift) error
|
||||||
|
// UpdateTx 事务更新
|
||||||
|
UpdateTx(ctx context.Context, tx *gorm.DB, data *Gift) error
|
||||||
|
FindByPlatformGift(ctx context.Context, platform string, giftId string) (*Gift, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
customGiftModel struct {
|
||||||
|
*defaultGiftModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewGiftModel returns a model for the database table.
|
||||||
|
func NewGiftModel(conn *gorm.DB) GiftModel {
|
||||||
|
return &customGiftModel{
|
||||||
|
defaultGiftModel: newGiftModel(conn),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customGiftModel) Transaction(ctx context.Context, tx *gorm.DB, fn func(tx *gorm.DB) error) error {
|
||||||
|
return withTx(ctx, m.conn, tx).Transaction(func(tx *gorm.DB) error {
|
||||||
|
return fn(tx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customGiftModel) InsertTx(ctx context.Context, tx *gorm.DB, data *Gift) error {
|
||||||
|
err := withTx(ctx, m.conn, tx).Create(&data).Error
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customGiftModel) UpdateTx(ctx context.Context, tx *gorm.DB, data *Gift) error {
|
||||||
|
err := withTx(ctx, m.conn, tx).Save(data).Error
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customGiftModel) FindByPlatformGift(ctx context.Context, platform string, giftId string) (*Gift, error) {
|
||||||
|
var resp Gift
|
||||||
|
db := m.conn.WithContext(ctx)
|
||||||
|
err := db.Model(&Gift{}).
|
||||||
|
Where("platform = ? AND gift_id = ?", platform, giftId).
|
||||||
|
Take(&resp).Error
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case gormc.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ UserGiftModel = (*customUserGiftModel)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// UserGiftModel is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in customUserGiftModel.
|
||||||
|
UserGiftModel interface {
|
||||||
|
userGiftModel
|
||||||
|
}
|
||||||
|
|
||||||
|
customUserGiftModel struct {
|
||||||
|
*defaultUserGiftModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewUserGiftModel returns a model for the database table.
|
||||||
|
func NewUserGiftModel(conn *gorm.DB) UserGiftModel {
|
||||||
|
return &customUserGiftModel{
|
||||||
|
defaultUserGiftModel: newUserGiftModel(conn),
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"git.noahlan.cn/northlan/ntools-go/gorm-zero/gormc"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ UserIntegralModel = (*customUserIntegralModel)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// UserIntegralModel is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in customUserIntegralModel.
|
||||||
|
UserIntegralModel interface {
|
||||||
|
userIntegralModel
|
||||||
|
Transact(ctx context.Context, tx *gorm.DB, fn func(tx *gorm.DB) error) error
|
||||||
|
InsertTx(ctx context.Context, tx *gorm.DB, data *UserIntegral) error
|
||||||
|
UpdateIntegralTx(ctx context.Context, tx *gorm.DB, userId, addon int64) error
|
||||||
|
FindIntegral(ctx context.Context, tx *gorm.DB, userId int64) (int64, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
customUserIntegralModel struct {
|
||||||
|
*defaultUserIntegralModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewUserIntegralModel returns a model for the database table.
|
||||||
|
func NewUserIntegralModel(conn *gorm.DB) UserIntegralModel {
|
||||||
|
return &customUserIntegralModel{
|
||||||
|
defaultUserIntegralModel: newUserIntegralModel(conn),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customUserIntegralModel) Transact(ctx context.Context, tx *gorm.DB, fn func(tx *gorm.DB) error) error {
|
||||||
|
return withTx(ctx, m.conn, tx).Transaction(fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customUserIntegralModel) InsertTx(ctx context.Context, tx *gorm.DB, data *UserIntegral) error {
|
||||||
|
err := withTx(ctx, m.conn, tx).Create(&data).Error
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customUserIntegralModel) UpdateIntegralTx(ctx context.Context, tx *gorm.DB, userId, change int64) error {
|
||||||
|
if change < 0 {
|
||||||
|
return errors.New("无法将积分更新至负数")
|
||||||
|
}
|
||||||
|
db := withTx(ctx, m.conn, tx)
|
||||||
|
|
||||||
|
result := db.Table(m.table).
|
||||||
|
Where("user_id = ?", userId).
|
||||||
|
Update("integral", change)
|
||||||
|
if result.Error != nil {
|
||||||
|
return result.Error
|
||||||
|
}
|
||||||
|
if result.RowsAffected == 0 {
|
||||||
|
return ErrRowsAffectedZero
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customUserIntegralModel) FindIntegral(ctx context.Context, tx *gorm.DB, userId int64) (int64, error) {
|
||||||
|
var resp int64
|
||||||
|
err := withTx(ctx, m.conn, tx).Table(m.table).
|
||||||
|
Select(fmt.Sprintf("%s.integral", m.table)).
|
||||||
|
Where("user_id = ?", userId).Take(&resp).Error
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return resp, nil
|
||||||
|
case gormc.ErrNotFound:
|
||||||
|
return 0, ErrNotFound
|
||||||
|
default:
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ UserNobilityModel = (*customUserNobilityModel)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// UserNobilityModel is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in customUserNobilityModel.
|
||||||
|
UserNobilityModel interface {
|
||||||
|
userNobilityModel
|
||||||
|
}
|
||||||
|
|
||||||
|
customUserNobilityModel struct {
|
||||||
|
*defaultUserNobilityModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewUserNobilityModel returns a model for the database table.
|
||||||
|
func NewUserNobilityModel(conn *gorm.DB) UserNobilityModel {
|
||||||
|
return &customUserNobilityModel{
|
||||||
|
defaultUserNobilityModel: newUserNobilityModel(conn),
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,35 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql/driver"
|
||||||
"errors"
|
"errors"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotFound = gorm.ErrRecordNotFound
|
var ErrNotFound = gorm.ErrRecordNotFound
|
||||||
var ErrRowsAffectedZero = errors.New("RowsAffected zero")
|
var ErrRowsAffectedZero = errors.New("RowsAffected zero")
|
||||||
|
|
||||||
|
// BitBool is an implementation of a bool for the MySQL type BIT(1).
|
||||||
|
// This type allows you to avoid wasting an entire byte for MySQL's boolean type TINYINT.
|
||||||
|
type BitBool bool
|
||||||
|
|
||||||
|
// Value implements the driver.Valuer interface,
|
||||||
|
// and turns the BitBool into a bitfield (BIT(1)) for MySQL storage.
|
||||||
|
func (b BitBool) Value() (driver.Value, error) {
|
||||||
|
if b {
|
||||||
|
return []byte{1}, nil
|
||||||
|
} else {
|
||||||
|
return []byte{0}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan implements the sql.Scanner interface,
|
||||||
|
// and turns the bitfield incoming from MySQL into a BitBool
|
||||||
|
func (b *BitBool) Scan(src interface{}) error {
|
||||||
|
v, ok := src.([]byte)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("bad []byte type assertion")
|
||||||
|
}
|
||||||
|
*b = v[0] == 1
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -1,20 +1,47 @@
|
|||||||
Name: usercenter.rpc
|
Name: usercenter.rpc
|
||||||
ListenOn: 127.0.0.1:30001
|
ListenOn: 127.0.0.1:30001
|
||||||
|
Timeout: 5000
|
||||||
Etcd:
|
Etcd:
|
||||||
Hosts:
|
Hosts:
|
||||||
- 127.0.0.1:2379
|
- 127.0.0.1:2379
|
||||||
Key: usercenter.rpc.dev
|
Key: usercenter.rpc.dev
|
||||||
Timeout: 5000 # default is 2000
|
Timeout: 5000 # default is 2000
|
||||||
NonBlock: true
|
NonBlock: true
|
||||||
|
Log:
|
||||||
|
Mode: console
|
||||||
|
KeepDays: 7
|
||||||
|
Level: info
|
||||||
DB:
|
DB:
|
||||||
#DataSource: root:root@tcp(192.168.1.100:3306)/dmgame?charset=utf8mb4&loc=Asia%2FShanghai&parseTime=true
|
#DataSource: root:root@tcp(192.168.1.100:3306)/dmgame?charset=utf8mb4&loc=Asia%2FShanghai&parseTime=true
|
||||||
DataSource: root:root@tcp(127.0.0.1:3306)/dmgame?charset=utf8mb4&loc=Asia%2FShanghai&parseTime=true
|
DataSource: root:root@tcp(127.0.0.1:3306)/dmgame?charset=utf8mb4&loc=Asia%2FShanghai&parseTime=true
|
||||||
UserRetriever:
|
UserRetriever:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
UpdateDuration: 720 # 720 hours = 30 Day = 1 Month
|
UpdateDuration: 720 # 720 hours = 30 Day = 1 Month
|
||||||
|
Cron:
|
||||||
|
PlatformUser: "0 0/5 * * * ?" # 每隔5分钟执行一次
|
||||||
|
Nobility: "0 0/10 * * * ?" # 每隔10分钟执行一次
|
||||||
|
NobilityPlatforms: [ "bilibili" ] # 需要获取贵族的平台列表
|
||||||
|
Bilibili:
|
||||||
|
RoomId: 8722013
|
||||||
|
Mid: 6704420
|
||||||
|
RoomShortInfoApi: https://api.live.bilibili.com/room/v1/Room/room_init
|
||||||
|
TopListApi: https://api.live.bilibili.com/guard/topList
|
||||||
Rank:
|
Rank:
|
||||||
|
Enabled: false
|
||||||
|
Cron:
|
||||||
|
Update: "0/10 * * * * ?" # 10s一次
|
||||||
|
Persistence: "0 0/10 * * * ?" # 10min一次
|
||||||
|
GiftCollector:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
Log:
|
Platforms: [ "bilibili" ]
|
||||||
Mode: console
|
Cron:
|
||||||
KeepDays: 7
|
CollectGift: "0 0 0/6 * * ?" # 每隔6小时执行一次
|
||||||
Level: info
|
Integral:
|
||||||
|
# RMB到积分的转换
|
||||||
|
RMBToIntegral: 1000
|
||||||
|
# 平台礼物到RMB的转换
|
||||||
|
GiftToRMB:
|
||||||
|
bilibili: 0.001
|
||||||
|
# 平台免费礼物到积分的转换
|
||||||
|
FreeToIntegral:
|
||||||
|
bilibili: 0.0001
|
@ -0,0 +1,32 @@
|
|||||||
|
package gift
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"live-service/app/user_center/rpc/internal/svc"
|
||||||
|
"live-service/app/user_center/rpc/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserBuyNobilityLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUserBuyNobilityLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserBuyNobilityLogic {
|
||||||
|
return &UserBuyNobilityLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserBuyNobility 用户购买贵族
|
||||||
|
// 1. 记录送礼
|
||||||
|
// 2. 新增积分
|
||||||
|
func (l *UserBuyNobilityLogic) UserBuyNobility(in *pb.UserBuyNobilityReq) (*pb.UserBuyNobilityResp, error) {
|
||||||
|
// TODO 未完成
|
||||||
|
return &pb.UserBuyNobilityResp{}, nil
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
package gift
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"git.noahlan.cn/northlan/ntools-go/uuid"
|
||||||
|
"live-service/app/user_center/model"
|
||||||
|
"live-service/app/user_center/rpc/internal/logic/gift_collect"
|
||||||
|
"live-service/app/user_center/rpc/internal/logic/integral"
|
||||||
|
"live-service/app/user_center/rpc/internal/logic/platform_user"
|
||||||
|
"live-service/app/user_center/rpc/internal/svc"
|
||||||
|
"live-service/app/user_center/rpc/pb"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserSendGiftLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUserSendGiftLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserSendGiftLogic {
|
||||||
|
return &UserSendGiftLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserSendGift 用户赠送礼物
|
||||||
|
// 1. 记录用户赠送信息
|
||||||
|
// 2. 新增用户积分
|
||||||
|
func (l *UserSendGiftLogic) UserSendGift(in *pb.UserSendGiftReq) (*pb.UserSendGiftResp, error) {
|
||||||
|
// 首先获取用户id
|
||||||
|
var err error
|
||||||
|
sysUser, err := platform_user.NewRetrievePlatformUserLogic(l.ctx, l.svcCtx).RetrievePlatformUser(&pb.PlatformUserReq{
|
||||||
|
Platform: in.Platform,
|
||||||
|
PUid: in.PUid,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := &pb.UserSendGiftResp{
|
||||||
|
User: sysUser.User,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录送礼信息
|
||||||
|
{
|
||||||
|
dbUserGift := &model.UserGift{
|
||||||
|
Id: uuid.NextId(),
|
||||||
|
UserId: sysUser.User.Id,
|
||||||
|
Platform: in.Platform,
|
||||||
|
RoomId: in.RoomId,
|
||||||
|
GiftId: strconv.FormatInt(in.GiftId, 10),
|
||||||
|
GiftName: in.GiftName,
|
||||||
|
Num: in.Num,
|
||||||
|
}
|
||||||
|
if in.IsPaid {
|
||||||
|
dbUserGift.Price = in.Price
|
||||||
|
} else {
|
||||||
|
dbUserGift.FreePrice = in.Price
|
||||||
|
}
|
||||||
|
if err = l.svcCtx.UserGiftModel.Insert(l.ctx, dbUserGift); err != nil {
|
||||||
|
l.Logger.Errorf("记录用户[%d]送礼信息 [%d:%s:%d] 失败,操作继续...", sysUser.User.Id, in.GiftId, in.GiftName, in.Num)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 积分
|
||||||
|
{
|
||||||
|
// 待增加的积分
|
||||||
|
addonIntegral := calcIntegral(l.svcCtx.Config, in.Platform, in.IsPaid, float64(in.Price), in.Num)
|
||||||
|
if tmpMap, ok := gift_collect.Service.GetCacheByPlatform(in.Platform); ok {
|
||||||
|
if tmpData, ok := tmpMap[in.GiftId]; ok {
|
||||||
|
addonIntegral = calcIntegral(l.svcCtx.Config, in.Platform, tmpData.IsPaid, tmpData.Price, in.Num)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newIntegral, err := integral.NewChangeIntegralLogic(l.ctx, l.svcCtx).ChangeIntegral(&pb.ChangeIntegralReq{
|
||||||
|
UserId: sysUser.User.Id,
|
||||||
|
Change: addonIntegral,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp.Integral = newIntegral
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package gift
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
|
"live-service/app/user_center/rpc/internal/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func calcIntegral(cfg config.Config, platform string, isPaid bool, price float64, num int64) int64 {
|
||||||
|
giftToRMBRadio, _ := cfg.Integral.GiftToRMB[platform]
|
||||||
|
freeToIntegralRadio, _ := cfg.Integral.FreeToIntegral[platform]
|
||||||
|
rmbToIntegral := cfg.Integral.RMBToIntegral
|
||||||
|
|
||||||
|
var newPrice float64
|
||||||
|
if isPaid {
|
||||||
|
newPrice = price * giftToRMBRadio
|
||||||
|
} else {
|
||||||
|
newPrice = price * freeToIntegralRadio
|
||||||
|
}
|
||||||
|
|
||||||
|
decimal.DivisionPrecision = 2
|
||||||
|
return decimal.NewFromFloat(newPrice).
|
||||||
|
Mul(decimal.NewFromInt(num)).
|
||||||
|
Mul(decimal.NewFromFloat(rmbToIntegral)).
|
||||||
|
Round(0).IntPart()
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package gift_collect
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/robfig/cron/v3"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
pbMq "live-service/app/pb/mq"
|
||||||
|
"live-service/app/user_center/rpc/internal/svc"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Service *GiftCollector
|
||||||
|
|
||||||
|
type (
|
||||||
|
GiftData struct {
|
||||||
|
Id int64 // 礼物ID
|
||||||
|
Name string // 礼物名称
|
||||||
|
Price float64 // 礼物单价(rmb)
|
||||||
|
IsPaid bool // 是否收费礼物
|
||||||
|
}
|
||||||
|
GiftCollector struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
cron *cron.Cron
|
||||||
|
|
||||||
|
collectorMapper map[string]CollectorFunc
|
||||||
|
|
||||||
|
// cacheGift 礼物缓存 platform:giftId:giftData
|
||||||
|
cacheGift map[string]map[int64]GiftData
|
||||||
|
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectorFunc func(ctx context.Context, svcCtx *svc.ServiceContext) (ret map[int64]GiftData, err error)
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitCollector(svcCtx *svc.ServiceContext) {
|
||||||
|
ctx := context.Background()
|
||||||
|
Service = &GiftCollector{
|
||||||
|
ctx: context.Background(),
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
cron: cron.New(cron.WithSeconds()),
|
||||||
|
collectorMapper: map[string]CollectorFunc{
|
||||||
|
pbMq.Platform_name[int32(pbMq.Platform_bilibili)]: GiftCollectorBilibili,
|
||||||
|
},
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
|
||||||
|
if !svcCtx.Config.GiftCollector.Enabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Service.startJob()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *GiftCollector) startJob() {
|
||||||
|
cfg := c.svcCtx.Config.GiftCollector
|
||||||
|
// 先执行一次
|
||||||
|
c.collectGift(cfg.Platforms...)
|
||||||
|
|
||||||
|
_, _ = c.cron.AddFunc(cfg.Cron.CollectGift, func() {
|
||||||
|
c.collectGift(cfg.Platforms...)
|
||||||
|
})
|
||||||
|
c.cron.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *GiftCollector) collectGift(platforms ...string) {
|
||||||
|
for _, platform := range platforms {
|
||||||
|
if handle, ok := c.collectorMapper[platform]; ok {
|
||||||
|
ret, err := handle(c.ctx, c.svcCtx)
|
||||||
|
if err != nil {
|
||||||
|
// TODO 打印
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// caching
|
||||||
|
c.cacheGift[platform] = ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCacheByPlatform 获取缓存中的礼物信息
|
||||||
|
func (c *GiftCollector) GetCacheByPlatform(platform string) (map[int64]GiftData, bool) {
|
||||||
|
data, ok := c.cacheGift[platform]
|
||||||
|
return data, ok
|
||||||
|
}
|
@ -0,0 +1,117 @@
|
|||||||
|
package gift_collect
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"git.noahlan.cn/northlan/ntools-go/uuid"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"io/ioutil"
|
||||||
|
"live-service/app/user_center/model"
|
||||||
|
"live-service/app/user_center/rpc/internal/svc"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CoinTypeGold = "gold"
|
||||||
|
CoinTypeSilver = "silver"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
bilibiliGift struct {
|
||||||
|
Id int64 `json:"id"` // 礼物ID
|
||||||
|
Name string `json:"name"` // 礼物名称
|
||||||
|
Price int64 `json:"price"` // 礼物单价
|
||||||
|
CoinType string `json:"coin_type"` // 瓜子类型 gold金瓜子 silver银瓜子
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func isPaidGift(coinType string) bool {
|
||||||
|
if coinType == CoinTypeGold {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if coinType == CoinTypeSilver {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func GiftCollectorBilibili(ctx context.Context, svcCtx *svc.ServiceContext) (ret map[int64]GiftData, err error) {
|
||||||
|
const platform = "bilibili"
|
||||||
|
radio, _ := svcCtx.Config.Integral.GiftToRMB[platform]
|
||||||
|
|
||||||
|
// 1. 读取API
|
||||||
|
httpResp, err := http.Get("https://api.live.bilibili.com/xlive/web-room/v1/giftPanel/giftConfig?platform=app")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resBody, err := ioutil.ReadAll(httpResp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var responseData struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Data struct {
|
||||||
|
List []bilibiliGift `json:"list"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(resBody, &responseData)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 2. 事务分批入库 限定每次分批入库数量
|
||||||
|
batchSize := 50
|
||||||
|
dataLen := len(responseData.Data.List)
|
||||||
|
batches := dataLen / batchSize
|
||||||
|
if dataLen%batchSize != 0 {
|
||||||
|
batches += 1
|
||||||
|
}
|
||||||
|
ret = make(map[int64]GiftData)
|
||||||
|
for i := 0; i < batches; i++ {
|
||||||
|
// TODO 错误处理
|
||||||
|
_ = svcCtx.GiftModel.Transaction(ctx, nil, func(tx *gorm.DB) error {
|
||||||
|
lenJ := (i + 1) * batchSize
|
||||||
|
if lenJ > dataLen {
|
||||||
|
lenJ = dataLen
|
||||||
|
}
|
||||||
|
for j := i * batchSize; j < lenJ; j++ {
|
||||||
|
gift := responseData.Data.List[j]
|
||||||
|
|
||||||
|
dbGift := &model.Gift{
|
||||||
|
Id: uuid.NextId(),
|
||||||
|
GiftId: strconv.FormatInt(gift.Id, 10),
|
||||||
|
GiftName: gift.Name,
|
||||||
|
Platform: platform,
|
||||||
|
}
|
||||||
|
giftData := GiftData{
|
||||||
|
Id: gift.Id,
|
||||||
|
Name: gift.Name,
|
||||||
|
}
|
||||||
|
if isPaidGift(gift.CoinType) {
|
||||||
|
dbGift.PPricePaid = gift.Price
|
||||||
|
dbGift.Price = float64(gift.Price) * float64(radio)
|
||||||
|
|
||||||
|
giftData.IsPaid = true
|
||||||
|
giftData.Price = dbGift.Price
|
||||||
|
} else {
|
||||||
|
dbGift.PPriceFree = gift.Price
|
||||||
|
|
||||||
|
giftData.IsPaid = false
|
||||||
|
giftData.Price = float64(dbGift.PPriceFree)
|
||||||
|
}
|
||||||
|
ret[giftData.Id] = giftData
|
||||||
|
|
||||||
|
if err = svcCtx.GiftModel.UpdateTx(ctx, tx, dbGift); err != nil {
|
||||||
|
if errors.Is(err, model.ErrRowsAffectedZero) {
|
||||||
|
err = nil
|
||||||
|
_ = svcCtx.GiftModel.InsertTx(ctx, tx, dbGift)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package gift_collect
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestA(t *testing.T) {
|
||||||
|
count := 10
|
||||||
|
batchSize := 5
|
||||||
|
batches := 0
|
||||||
|
if count%batchSize == 0 {
|
||||||
|
batches = count / batchSize
|
||||||
|
} else {
|
||||||
|
batches = count/batchSize + 1
|
||||||
|
}
|
||||||
|
for i := 0; i < batches; i++ {
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println(i)
|
||||||
|
fmt.Println()
|
||||||
|
lenJ := (i + 1) * batchSize
|
||||||
|
if lenJ > count {
|
||||||
|
lenJ = count
|
||||||
|
}
|
||||||
|
for j := i * batchSize; j < lenJ; j++ {
|
||||||
|
fmt.Println(j)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("count: %d size: %d batches: %d\n", count, batchSize, batches)
|
||||||
|
fmt.Printf("求余: %v", count%batchSize)
|
||||||
|
|
||||||
|
//data := make([]int, 0, 322)
|
||||||
|
//for i := 0; i < 322; i++ {
|
||||||
|
// data = append(data, i)
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//batchSize := 50
|
||||||
|
//tmpList := make([]int, 0, batchSize)
|
||||||
|
//for i, gift := range data {
|
||||||
|
// tmpList = append(tmpList, gift)
|
||||||
|
// if (i+1)%batchSize == 0 || (i+1) == len(data) {
|
||||||
|
// // 一次
|
||||||
|
// fmt.Printf("%d 次 %+v\n", (i+1)%batchSize, tmpList)
|
||||||
|
// tmpList = make([]int, 0, batchSize)
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package integral
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"live-service/app/user_center/model"
|
||||||
|
"live-service/common/nerr"
|
||||||
|
|
||||||
|
"live-service/app/user_center/rpc/internal/svc"
|
||||||
|
"live-service/app/user_center/rpc/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ChangeIntegralLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewChangeIntegralLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ChangeIntegralLogic {
|
||||||
|
return &ChangeIntegralLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangeIntegral 新增用户积分
|
||||||
|
func (l *ChangeIntegralLogic) ChangeIntegral(in *pb.ChangeIntegralReq) (*pb.ChangeIntegralResp, error) {
|
||||||
|
if err := l.svcCtx.UserIntegralModel.Transact(l.ctx, nil, func(tx *gorm.DB) error {
|
||||||
|
integral, err := l.svcCtx.UserIntegralModel.FindIntegral(l.ctx, tx, in.UserId)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, model.ErrNotFound) {
|
||||||
|
if in.Change < 0 {
|
||||||
|
return errors.New("用户积分不足")
|
||||||
|
}
|
||||||
|
// 用户积分记录不存在,进行插入
|
||||||
|
if err = l.svcCtx.UserIntegralModel.InsertTx(l.ctx, tx, &model.UserIntegral{
|
||||||
|
UserId: in.UserId,
|
||||||
|
Integral: in.Change,
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "插入用户积分失败")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return errors.Wrap(err, "获取当前用户积分失败")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if integral+in.Change < 0 {
|
||||||
|
return errors.New("用户积分不足")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = l.svcCtx.UserIntegralModel.UpdateIntegralTx(l.ctx, tx, in.UserId, integral+in.Change); err != nil {
|
||||||
|
return errors.Wrap(err, "更新用户积分失败")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return nil, errors.Wrapf(nerr.NewWithErr(err), "记录积分-事务执行失败, err:%+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询当前用户积分
|
||||||
|
integral, err := l.svcCtx.UserIntegralModel.FindIntegral(l.ctx, nil, in.UserId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(nerr.NewWithMsg("查询用户积分失败"), "查询用户积分失败, err:%+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.ChangeIntegralResp{
|
||||||
|
UserId: in.UserId,
|
||||||
|
Change: in.Change,
|
||||||
|
Integral: integral,
|
||||||
|
}, nil
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package integral
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"live-service/common/nerr"
|
||||||
|
|
||||||
|
"live-service/app/user_center/rpc/internal/svc"
|
||||||
|
"live-service/app/user_center/rpc/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetUserIntegralLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetUserIntegralLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserIntegralLogic {
|
||||||
|
return &GetUserIntegralLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserIntegral 获取用户积分
|
||||||
|
func (l *GetUserIntegralLogic) GetUserIntegral(in *pb.UserIdResp) (*pb.UserIntegralResp, error) {
|
||||||
|
// 查询当前用户积分
|
||||||
|
integral, err := l.svcCtx.UserIntegralModel.FindIntegral(l.ctx, nil, in.UserId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(nerr.NewWithCode(nerr.DBError), "查询用户积分失败, err:%+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.UserIntegralResp{
|
||||||
|
UserId: in.UserId,
|
||||||
|
Integral: integral,
|
||||||
|
}, nil
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package platform_user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"live-service/common/nerr"
|
||||||
|
|
||||||
|
"live-service/app/user_center/rpc/internal/svc"
|
||||||
|
"live-service/app/user_center/rpc/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetUserIdByPUidLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetUserIdByPUidLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserIdByPUidLogic {
|
||||||
|
return &GetUserIdByPUidLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserIdByPUid 通过平台用户id获取系统用户ID
|
||||||
|
func (l *GetUserIdByPUidLogic) GetUserIdByPUid(in *pb.PlatformUserReq) (*pb.UserIdResp, error) {
|
||||||
|
sysUserId, err := l.svcCtx.UserPlatformModel.FindUserIdByPlatform(l.ctx, in.Platform, in.PUid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(nerr.NewWithCode(nerr.DBError), "获取系统用户ID失败, err:%+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.UserIdResp{
|
||||||
|
UserId: sysUserId,
|
||||||
|
}, nil
|
||||||
|
}
|
@ -1,83 +0,0 @@
|
|||||||
package logic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"git.noahlan.cn/northlan/ntools-go/uuid"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
"live-service/app/user_center/model"
|
|
||||||
"live-service/app/user_center/rpc/internal/svc"
|
|
||||||
"live-service/app/user_center/rpc/pb"
|
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
|
||||||
)
|
|
||||||
|
|
||||||
type RetrievePlatformUserLogic struct {
|
|
||||||
ctx context.Context
|
|
||||||
svcCtx *svc.ServiceContext
|
|
||||||
|
|
||||||
logx.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRetrievePlatformUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RetrievePlatformUserLogic {
|
|
||||||
return &RetrievePlatformUserLogic{
|
|
||||||
ctx: ctx,
|
|
||||||
svcCtx: svcCtx,
|
|
||||||
Logger: logx.WithContext(ctx),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetrievePlatformUser 查询或创建用户(此时不查询平台用户信息)
|
|
||||||
func (l *RetrievePlatformUserLogic) RetrievePlatformUser(in *pb.PlatformUserReq) (*pb.PlatformUserResp, error) {
|
|
||||||
var username string
|
|
||||||
var dbPlatformUser *model.UserPlatform
|
|
||||||
|
|
||||||
err := l.svcCtx.UserPlatformModel.Transaction(l.ctx, nil, func(tx *gorm.DB) error {
|
|
||||||
var err error
|
|
||||||
if dbPlatformUser, err = l.svcCtx.UserPlatformModel.FindOneByPlatformAndPUid(l.ctx, tx, in.Platform, in.PUid); err != nil {
|
|
||||||
if !errors.Is(err, model.ErrNotFound) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if dbPlatformUser != nil {
|
|
||||||
if one, err := l.svcCtx.UserModel.FindOneTx(l.ctx, tx, dbPlatformUser.UserId); err != nil {
|
|
||||||
username = one.Username
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// insert
|
|
||||||
newId := uuid.NextId()
|
|
||||||
if err := l.svcCtx.UserModel.InsertTx(l.ctx, tx, &model.User{Id: newId}); err != nil {
|
|
||||||
return errors.Wrap(err, "插入用户数据失败")
|
|
||||||
}
|
|
||||||
dbPlatformUser = &model.UserPlatform{
|
|
||||||
Id: uuid.NextId(),
|
|
||||||
UserId: newId,
|
|
||||||
Platform: in.Platform,
|
|
||||||
PUid: in.PUid,
|
|
||||||
PInfo: "{}",
|
|
||||||
}
|
|
||||||
if err := l.svcCtx.UserPlatformModel.InsertTx(l.ctx, tx, dbPlatformUser); err != nil {
|
|
||||||
return errors.Wrap(err, "插入平台用户数据失败")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "查询或创建用户-事务执行失败, err:%+v", err)
|
|
||||||
}
|
|
||||||
return &pb.PlatformUserResp{
|
|
||||||
User: l.buildPBUser(username, dbPlatformUser),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *RetrievePlatformUserLogic) buildPBUser(username string, dbPlatformUser *model.UserPlatform) *pb.User {
|
|
||||||
return &pb.User{
|
|
||||||
Id: dbPlatformUser.UserId,
|
|
||||||
Username: username,
|
|
||||||
Platform: dbPlatformUser.Platform,
|
|
||||||
PUid: dbPlatformUser.PUid,
|
|
||||||
PUname: dbPlatformUser.PUname,
|
|
||||||
PAvatar: dbPlatformUser.PAvatar,
|
|
||||||
PInfo: dbPlatformUser.PInfo,
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
func (m *default{{.upperStartCamelObject}}Model) Delete(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) error {
|
||||||
|
{{if .withCache}}{{if .containsIndexCache}}data, err:=m.FindOne(ctx, {{.lowerStartCamelPrimaryKey}})
|
||||||
|
if err!=nil{
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
{{end}} {{.keys}}
|
||||||
|
err {{if .containsIndexCache}}={{else}}:={{end}} m.ExecCtx(ctx, func(conn *gorm.DB) *gorm.DB {
|
||||||
|
return conn.Delete(&{{.upperStartCamelObject}}{}, {{.lowerStartCamelPrimaryKey}})
|
||||||
|
}, {{.keyValues}}){{else}} err:= m.conn.WithContext(ctx).Delete(&{{.upperStartCamelObject}}{}, {{.lowerStartCamelPrimaryKey}}).Error
|
||||||
|
{{end}}
|
||||||
|
return err
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package {{.pkg}}
|
||||||
|
|
||||||
|
import "gorm.io/gorm"
|
||||||
|
|
||||||
|
var ErrNotFound = gorm.ErrRecordNotFound
|
@ -0,0 +1 @@
|
|||||||
|
{{.name}} {{.type}} {{.tag}} {{if .hasComment}}// {{.comment}}{{end}}
|
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
func (m *default{{.upperStartCamelObject}}Model) formatPrimary(primary interface{}) string {
|
||||||
|
return fmt.Sprintf("%s%v", {{.primaryKeyLeft}}, primary)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *default{{.upperStartCamelObject}}Model) queryPrimary(conn *gorm.DB, v, primary interface{}) error {
|
||||||
|
return conn.Model(&{{.upperStartCamelObject}}{}).Where("{{.originalPrimaryField}} = ?", primary).Take(v).Error
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
func (m *default{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}(ctx context.Context, {{.in}}) (*{{.upperStartCamelObject}}, error) {
|
||||||
|
{{if .withCache}}{{.cacheKey}}
|
||||||
|
var resp {{.upperStartCamelObject}}
|
||||||
|
err := m.QueryRowIndexCtx(ctx, &resp, {{.cacheKeyVariable}}, m.formatPrimary, func(conn *gorm.DB, v interface{}) (interface{}, error) {
|
||||||
|
if err := conn.Model(&{{.upperStartCamelObject}}{}).Where("{{.originalField}}", {{.lowerStartCamelField}}).Take(&resp).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resp.{{.upperStartCamelPrimaryKey}}, nil
|
||||||
|
}, m.queryPrimary)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case gormc.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}{{else}}var resp {{.upperStartCamelObject}}
|
||||||
|
err := m.conn.WithContext(ctx).Model(&{{.upperStartCamelObject}}{}).Where("{{.originalField}}", {{.lowerStartCamelField}}).Take(&resp).Error
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case gormc.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}{{end}}
|
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
func (m *default{{.upperStartCamelObject}}Model) FindOne(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error) {
|
||||||
|
{{if .withCache}}{{.cacheKey}}
|
||||||
|
var resp {{.upperStartCamelObject}}
|
||||||
|
err := m.QueryRowCtx(ctx, &resp, {{.cacheKeyVariable}}, func(conn *gorm.DB) *gorm.DB {
|
||||||
|
return conn.Where("id = ?", {{.lowerStartCamelPrimaryKey}})
|
||||||
|
})
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case gormc.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}{{else}}var resp {{.upperStartCamelObject}}
|
||||||
|
err := m.conn.WithContext(ctx).Model(&{{.upperStartCamelObject}}{}).Where("{{.originalPrimaryKey}} = ?", {{.lowerStartCamelPrimaryKey}}).Take(&resp).Error
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case gormc.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}{{end}}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"git.noahlan.cn/northlan/ntools-go/gorm-zero/gormc"
|
||||||
|
"strings"
|
||||||
|
{{if .time}}"time"{{end}}
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||||
|
"github.com/zeromicro/go-zero/core/stringx"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
@ -0,0 +1,12 @@
|
|||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
{{if .time}}"time"{{end}}
|
||||||
|
|
||||||
|
"git.noahlan.cn/northlan/ntools-go/gorm-zero/gormc"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||||
|
"github.com/zeromicro/go-zero/core/stringx"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
func (m *default{{.upperStartCamelObject}}Model) Insert(ctx context.Context, data *{{.upperStartCamelObject}}) error {
|
||||||
|
{{if .withCache}}{{.keys}}
|
||||||
|
err := m.ExecCtx(ctx, func(conn *gorm.DB) *gorm.DB {
|
||||||
|
return conn.Create(&data)
|
||||||
|
}, {{.keyValues}}){{else}}err:=m.conn.WithContext(ctx).Create(&data).Error{{end}}
|
||||||
|
return err
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
Delete(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) error
|
@ -0,0 +1 @@
|
|||||||
|
FindOneBy{{.upperField}}(ctx context.Context, {{.in}}) (*{{.upperStartCamelObject}}, error)
|
@ -0,0 +1 @@
|
|||||||
|
FindOne(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error)
|
@ -0,0 +1 @@
|
|||||||
|
Insert(ctx context.Context, data *{{.upperStartCamelObject}}) error
|
@ -0,0 +1 @@
|
|||||||
|
Update(ctx context.Context, data *{{.upperStartCamelObject}}) error
|
@ -0,0 +1,13 @@
|
|||||||
|
// Code generated by goctl. DO NOT EDIT!
|
||||||
|
|
||||||
|
package {{.pkg}}
|
||||||
|
{{.imports}}
|
||||||
|
{{.vars}}
|
||||||
|
{{.types}}
|
||||||
|
{{.new}}
|
||||||
|
{{.insert}}
|
||||||
|
{{.find}}
|
||||||
|
{{.update}}
|
||||||
|
{{.delete}}
|
||||||
|
{{.extraMethod}}
|
||||||
|
{{.tableName}}
|
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
func new{{.upperStartCamelObject}}Model(conn *gorm.DB{{if .withCache}}, c cache.CacheConf{{end}}) *default{{.upperStartCamelObject}}Model {
|
||||||
|
return &default{{.upperStartCamelObject}}Model{
|
||||||
|
{{if .withCache}}CachedConn: gormc.NewConn(conn, c){{else}}conn:conn{{end}},
|
||||||
|
table: {{.table}},
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package {{.pkg}}
|
||||||
|
{{if .withCache}}
|
||||||
|
import (
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
{{else}}
|
||||||
|
import (
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
{{end}}
|
||||||
|
var _ {{.upperStartCamelObject}}Model = (*custom{{.upperStartCamelObject}}Model)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// {{.upperStartCamelObject}}Model is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in custom{{.upperStartCamelObject}}Model.
|
||||||
|
{{.upperStartCamelObject}}Model interface {
|
||||||
|
{{.lowerStartCamelObject}}Model
|
||||||
|
}
|
||||||
|
|
||||||
|
custom{{.upperStartCamelObject}}Model struct {
|
||||||
|
*default{{.upperStartCamelObject}}Model
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// New{{.upperStartCamelObject}}Model returns a model for the database table.
|
||||||
|
func New{{.upperStartCamelObject}}Model(conn *gorm.DB{{if .withCache}}, c cache.CacheConf{{end}}) {{.upperStartCamelObject}}Model {
|
||||||
|
return &custom{{.upperStartCamelObject}}Model{
|
||||||
|
default{{.upperStartCamelObject}}Model: new{{.upperStartCamelObject}}Model(conn{{if .withCache}}, c{{end}}),
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
func (m *default{{.upperStartCamelObject}}Model) tableName() string {
|
||||||
|
return m.table
|
||||||
|
}
|
||||||
|
|
||||||
|
func ({{.upperStartCamelObject}}) TableName() string {
|
||||||
|
model := new{{.upperStartCamelObject}}Model(nil)
|
||||||
|
return model.tableName()
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
`gorm:"column:{{.field}}"`
|
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
type (
|
||||||
|
{{.lowerStartCamelObject}}Model interface{
|
||||||
|
{{.method}}
|
||||||
|
}
|
||||||
|
|
||||||
|
default{{.upperStartCamelObject}}Model struct {
|
||||||
|
{{if .withCache}}gormc.CachedConn{{else}}conn *gorm.DB{{end}}
|
||||||
|
table string
|
||||||
|
}
|
||||||
|
|
||||||
|
{{.upperStartCamelObject}} struct {
|
||||||
|
{{.fields}}
|
||||||
|
}
|
||||||
|
)
|
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
func (m *default{{.upperStartCamelObject}}Model) Update(ctx context.Context, data *{{.upperStartCamelObject}}) error {
|
||||||
|
{{if .withCache}}{{.keys}}
|
||||||
|
err := m.ExecCtx(ctx, func(conn *gorm.DB) *gorm.DB {
|
||||||
|
return conn.Save(data)
|
||||||
|
}, {{.keyValues}}){{else}}err:=m.conn.WithContext(ctx).Save(data).Error{{end}}
|
||||||
|
return err
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
var (
|
||||||
|
{{.lowerStartCamelObject}}FieldNames = builder.RawFieldNames(&{{.upperStartCamelObject}}{}{{if .postgreSql}},true{{end}})
|
||||||
|
{{.lowerStartCamelObject}}Rows = strings.Join({{.lowerStartCamelObject}}FieldNames, ",")
|
||||||
|
{{.lowerStartCamelObject}}RowsExpectAutoSet = {{if .postgreSql}}strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, {{if .autoIncrement}}"{{.originalPrimaryKey}}",{{end}} "create_time", "update_time"), ","){{else}}strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, {{if .autoIncrement}}"{{.originalPrimaryKey}}",{{end}} "`create_time`", "`update_time`"), ","){{end}}
|
||||||
|
{{.lowerStartCamelObject}}RowsWithPlaceHolder = {{if .postgreSql}}builder.PostgreSqlJoin(stringx.Remove({{.lowerStartCamelObject}}FieldNames, "{{.originalPrimaryKey}}", "create_time", "update_time")){{else}}strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, "{{.originalPrimaryKey}}", "`create_time`", "`update_time`"), "=?,") + "=?"{{end}}
|
||||||
|
|
||||||
|
{{if .withCache}}{{.cacheKeys}}{{end}}
|
||||||
|
)
|
Loading…
Reference in New Issue