Initial commit

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-23 11:07:42 +08:00
co-authored by Claude Opus 5.5
commit 7974a42301
633 changed files with 120248 additions and 0 deletions
+40
View File
@@ -0,0 +1,40 @@
package cointransmod
type TagCoinTrans struct {
Id string
UserId string
UserName string
FlowDir string
TranType string
Amount string
BalanceBefore string
BalanceAfter string
OrderNo string
RelatedId string
Remark string
CreatedAt string
}
var FN struct {
CoinTrans TagCoinTrans
}
var TN struct {
CoinTrans string
}
func init() {
FN.CoinTrans.Id = "_id"
FN.CoinTrans.UserId = "userId"
FN.CoinTrans.UserName = "userName"
FN.CoinTrans.FlowDir = "flowDir"
FN.CoinTrans.TranType = "tranType"
FN.CoinTrans.Amount = "amount"
FN.CoinTrans.BalanceBefore = "balanceBefore"
FN.CoinTrans.BalanceAfter = "balanceAfter"
FN.CoinTrans.OrderNo = "orderNo"
FN.CoinTrans.RelatedId = "relatedId"
FN.CoinTrans.Remark = "remark"
FN.CoinTrans.CreatedAt = "createdAt"
TN.CoinTrans = "coin_trans"
}
+80
View File
@@ -0,0 +1,80 @@
package cointransmod
import (
"context"
"fmt"
"videoweb/pub/common/log"
"videoweb/pub/common/srvdef"
"videoweb/pub/mongos"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
var coll *mongos.Collection
func Init(ctx context.Context) {
coll = mongos.Shop.Coll(TN.CoinTrans)
initIndex(ctx)
}
func initIndex(ctx context.Context) {
indexes := []mongo.IndexModel{
// 按用户+时间倒序查流水(最常用)
{Keys: bson.D{
{Key: FN.CoinTrans.UserId, Value: 1},
{Key: FN.CoinTrans.CreatedAt, Value: -1},
}},
// 按交易类型筛选
{Keys: bson.D{{Key: FN.CoinTrans.TranType, Value: 1}}},
// 按订单号查(幂等校验)
{Keys: bson.D{{Key: FN.CoinTrans.OrderNo, Value: 1}}},
}
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
panic(fmt.Sprintf("(cointransmod:initIndex) Create Index failed! err:%+v:", err))
}
}
// InsertOneCoinTrans 写入一条流水记录
func InsertOneCoinTrans(ctx context.Context, doc *CoinTrans) *srvdef.SrvErr {
if _, err := coll.InsertOne(ctx, doc); err != nil {
log.Error("cointransmod:InsertOneCoinTrans failed", log.Any("doc", doc), log.E(err))
return srvdef.New(srvdef.ErrDbInsertError, "", "")
}
return nil
}
// FindManyCoinTrans 分页查询流水列表
func FindManyCoinTrans(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (CoinTransList, *srvdef.SrvErr) {
var data CoinTransList
if err := coll.Find(ctx, &data, filter, opts...); err != nil {
log.Warn("cointransmod:FindManyCoinTrans failed", log.E(err), log.Any("filter", filter))
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
}
return data, nil
}
// CountCoinTrans 统计流水条数
func CountCoinTrans(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
count, err := coll.Count(ctx, filter)
if err != nil {
log.Warn("cointransmod:CountCoinTrans failed", log.E(err), log.Any("filter", filter))
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
}
return count, nil
}
// StatSyncConsumeList 按 ID 游标增量拉取金币消费流水(统计中心)
func StatSyncConsumeList(ctx context.Context, startId int64, size int64) (CoinTransList, error) {
opt := (&options.FindOptions{}).SetLimit(size).SetSort(bson.D{{Key: FN.CoinTrans.Id, Value: 1}})
filter := bson.M{
FN.CoinTrans.Id: bson.M{"$gt": startId},
FN.CoinTrans.FlowDir: FlowOut,
}
list := CoinTransList{}
if err := coll.Find(ctx, &list, filter, opt); err != nil {
return nil, err
}
return list, nil
}
+62
View File
@@ -0,0 +1,62 @@
package cointransmod
import "time"
// FlowDir 收支方向
type FlowDir int8
const (
FlowIn FlowDir = 1 // 收入(充值、赠送)
FlowOut FlowDir = -1 // 支出(消费、解锁)
)
func (f FlowDir) Desc() string {
if f == FlowIn {
return "收入"
}
return "支出"
}
// TranType 交易类型
type TranType int32
const (
TranTypeCoinRecharge TranType = 1 // 金币充值(购买金币)
TranTypeVipGiftCoin TranType = 2 // 购买会员赠送金币
TranTypeDarkAlley TranType = 3 // 历史遗留交易类型(已下线)
TranTypeVideoUnlock TranType = 4 // 视频解锁
TranTypeAdminAdjust TranType = 5 // 管理员手动调整
)
var TranTypeNameMap = map[TranType]string{
TranTypeCoinRecharge: "金币充值",
TranTypeVipGiftCoin: "会员赠送",
TranTypeDarkAlley: "历史交易",
TranTypeVideoUnlock: "视频解锁",
TranTypeAdminAdjust: "管理员调整",
}
func (t TranType) Desc() string {
if name, ok := TranTypeNameMap[t]; ok {
return name
}
return "未知"
}
// @table: coin_trans
type CoinTrans struct {
Id int64 `json:"id" bson:"_id"` // 唯一ID
UserId int64 `json:"userId" bson:"userId"` // 用户ID
UserName string `json:"userName" bson:"userName"` // 用户昵称(快照)
FlowDir FlowDir `json:"flowDir" bson:"flowDir"` // 收支方向:1收入 -1支出
TranType TranType `json:"tranType" bson:"tranType"` // 交易类型
Amount int64 `json:"amount" bson:"amount"` // 本次交易金币数(正整数)
BalanceBefore int64 `json:"balanceBefore" bson:"balanceBefore"` // 交易前余额
BalanceAfter int64 `json:"balanceAfter" bson:"balanceAfter"` // 交易后余额
OrderNo string `json:"orderNo" bson:"orderNo"` // 关联订单号(可为空)
RelatedId int64 `json:"relatedId" bson:"relatedId"` // 关联内容ID(视频等,可为空)
Remark string `json:"remark" bson:"remark"` // 备注描述
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 交易时间
}
type CoinTransList []*CoinTrans