Initial commit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 13:57:10 +08:00
co-authored by Claude Opus 5
commit 8679200f41
1897 changed files with 257900 additions and 0 deletions
+111
View File
@@ -0,0 +1,111 @@
package statser
import (
"91porn-server/common/maths"
"fmt"
"math"
"time"
)
type DailyRecord struct {
Date time.Time `json:"date"` //日期
//日常
NewUserCount float64 `json:"newUserCount"` //新增用户数
SumUserCount float64 `json:"sumUserCount"` //用户数合计 sum = NewUserCount_1 + NewUserCount_2 + ... + NewUserCount_n
BindUserCount float64 `json:"bindUserCount"` //绑定用户数
SumBindUserCount float64 `json:"sumBindUserCount"` //绑定用户数合计 sum = BindUserCount_1 + BindUserCount_2 + ... + BindUserCount_n
NewBindUserCount float64 `json:"newBindUserCount"` //新增绑定用户数
VisitUserCount float64 `json:"visitUserCount"` //访问用户数
SumVisitUserCount float64 `json:"sumVisitUserCount"` //访问用户数合计 sum = VisitUserCount_1 + VisitUserCount_2 + ... + VisitUserCount_n
AveVisitUserCount float64 `json:"aveVisitUserCount"` //平均访问用户数 = SumVisitUserCount / n
IOSRetainUserRate2Day string `json:"iosRetainUserRate2Day"` //IOS次日用户留存率
ANDRetainUserRate2Day string `json:"andRetainUserRate2Day"` //安卓次日用户留存率
H5RetainUserRate2Day string `json:"h5RetainUserRate2Day"` //H5次日用户留存率
RetainUserRate2Day string `json:"retainUserRate2Day"` //次日用户留存率
RetainUserRate3Day string `json:"retainUserRate3Day"` //3日用户留存率
RetainUserRate7Day string `json:"retainUserRate7Day"` //7日用户留存率
RetainUserRate15Day string `json:"retainUserRate15Day"` //15日用户留存率
RetainUserRate30Day string `json:"retainUserRate30Day"` //30日用户留存率
//视屏
NewVideoCount int64 `json:"newVideoCount"` //新增短视屏数
PlayUserCount float64 `json:"playUserCount"` //播放视屏人数
PeakViewCount int64 `json:"peakViewCount"` //[未完成]峰值观看数
PeakViewTime int64 `json:"peakViewTime"` //[未完成]峰值观看时长
EffecViewCount int64 `json:"effecViewCount"` //[未完成]有效观看数
AveEffecViewTime int64 `json:"aveEffecViewTime"` //[未完成]平均有效观看时长
//消费
PayGold int64 `json:"payAmount"` //消费金币 = 消费付费视屏金额 + 消费vip金额
PayVipGold int64 `json:"payVipAmount"` //购买VIP金币
PayVidGold int64 `json:"payVidAmount"` //视频消费金币
PayVipUserCount float64 `json:"payVipUserCount"` //购买VIP人数
PayUserCount float64 `json:"payUserCount"` //消费人数
NewAndPayUserCount float64 `json:"newAndPayUserCount"` //新增并消费人数
SumPayGold float64 `json:"sumPayAmount"` //消费金币合计 = PayAmount_1 + PayAmount_2 + ... + PayAmount_n
AvePayGold int64 `json:"avePayAmount"` //平均消费金币 = SumPayGold / n
//充值
MerchantRechargeAmount float64 `json:"merchantRechargeAmount"` //[未完成]商人充值额度
OnlineRechargeAmount float64 `json:"onlineRechargeAmount"` //在线用户充值金额
TotalRechargeAmount float64 `json:"totalRechargeAmount"` //总充值金额 = //在线用户充值金额 + 商人充值额度
RechargeUserCount float64 `json:"rechargeUserCount"` //充值用户数
NewAndRechargeUserCount float64 `json:"newAndRechargeUserCount"` //新增充值用户数
ARPU int64 `json:"arpu"` //Average Revenue Per User 每用户平均收入=总收入(总充值)/访问用户数
ARPPU int64 `json:"arppu"` //Average Revenue Per Paying User 每充值用户平均收益=总收入(总充值)/充值用户数
SumRechargeAmount float64 `json:"sumRechargeAmount"` //充值金额合计 sum = RechargeUserCount_1 + RechargeUserCount_2 + ... + RechargeUserCount_n
AveRechargeAmount int64 `json:"aveRechargeAmount"` //平均充值金额 = SumRechargeAmount / n
//提现
GoldWithdrawAmount float64 `json:"goldWithdrawAmount"` //金币提现金额
ProxyWithdrawAmount float64 `json:"proxyWithdrawAmount"` //全民代理提现金额
}
func (this *DailyRecord) BaiYuan() *DailyRecord {
this.MerchantRechargeAmount = maths.ToFloat64_b2(this.MerchantRechargeAmount / 100)
this.OnlineRechargeAmount = maths.ToFloat64_b2(this.OnlineRechargeAmount / 100)
this.TotalRechargeAmount = maths.ToFloat64_b2(this.TotalRechargeAmount / 100)
this.SumRechargeAmount = maths.ToFloat64_b2(this.SumRechargeAmount / 100)
this.GoldWithdrawAmount = maths.ToFloat64_b2(this.GoldWithdrawAmount / 100)
this.ProxyWithdrawAmount = maths.ToFloat64_b2(this.ProxyWithdrawAmount / 100)
this.NewUserCount = maths.ToFloat64_b2(this.NewUserCount / 100)
this.SumUserCount = maths.ToFloat64_b2(this.SumUserCount / 100)
this.BindUserCount = maths.ToFloat64_b2(this.BindUserCount / 100)
this.SumBindUserCount = maths.ToFloat64_b2(this.SumBindUserCount / 100)
this.NewBindUserCount = maths.ToFloat64_b2(this.NewBindUserCount / 100)
this.VisitUserCount = maths.ToFloat64_b2(this.VisitUserCount / 100)
this.SumVisitUserCount = maths.ToFloat64_b2(this.SumVisitUserCount / 100)
this.AveVisitUserCount = maths.ToFloat64_b2(this.AveVisitUserCount / 100)
this.PlayUserCount = maths.ToFloat64_b2(this.PlayUserCount / 100)
this.PayVipUserCount = maths.ToFloat64_b2(this.PayVipUserCount / 100)
this.PayUserCount = maths.ToFloat64_b2(this.PayUserCount / 100)
this.NewAndPayUserCount = maths.ToFloat64_b2(this.NewAndPayUserCount / 100)
this.RechargeUserCount = maths.ToFloat64_b2(this.RechargeUserCount / 100)
this.NewAndRechargeUserCount = maths.ToFloat64_b2(this.NewAndRechargeUserCount / 100)
return this
}
type DailyPages struct {
Total int64 `json:"total"`
List []*DailyRecord `json:"list"`
}
// 四舍五入
func Rounding(v float64) int64 {
return int64(math.Floor(v + 0.5))
}
func Percentage(v float64) string {
return fmt.Sprintf("%.3f%%", v*100)
}
func Divide(a, b int64) float64 {
if b == 0 {
return 0
}
return float64(a) / float64(b)
}
func toInt64(v *int64) int64 {
if v == nil {
return 0
}
return *v
}
+301
View File
@@ -0,0 +1,301 @@
package statser
import (
"91porn-server/common/maths"
"91porn-server/common/pageopt"
"91porn-server/common/timeutil/timerange"
"91porn-server/models/l/payvidlgmod"
"91porn-server/models/s/statordermod"
"91porn-server/models/v/prdcthsomod"
"91porn-server/models/v/productmod"
"91porn-server/models/v/rchgordmod"
"91porn-server/models/v/txnmod"
"91porn-server/models/v/usermod"
"91porn-server/models/v/vidmod"
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
)
type OrderData struct {
CompleteRate string `json:"completeRate"` //完成率 = 完成订单数 / 总订单数
OrderCount int64 `json:"orderCount"` //生产订单数
CompleteOrderCount int64 `json:"completeOrderCount"` //完成订单数
OrderAmount float64 `json:"orderAmount"` //生产订单金额
CompleteOrderAmount float64 `json:"completeOrderAmount"` //完成订单的实际支付金额
PaidOrderCount int64 `json:"paidOrderCount"` //用户已支付金额/三方已出款金额
PaidAmount float64 `json:"paidAmount"` //用户已支付订单数/三方已出款订单数
}
func (o *OrderData) From(items statordermod.Items) {
o.CompleteRate = Percentage(Divide(items.CompleteOrderCount, items.OrderCount))
o.OrderCount = items.OrderCount
o.CompleteOrderCount = items.CompleteOrderCount
o.OrderAmount = float64(items.OrderAmount)
o.CompleteOrderAmount = float64(items.CompleteOrderAmount)
o.PaidOrderCount = items.PaidOrderCount
o.PaidAmount = float64(items.PaidAmount)
}
func (o *OrderData) BaiYuan() *OrderData {
o.OrderAmount = maths.ToFloat64_b2(o.OrderAmount / 100)
o.CompleteOrderAmount = maths.ToFloat64_b2(o.CompleteOrderAmount / 100)
o.PaidAmount = maths.ToFloat64_b2(o.PaidAmount / 100)
return o
}
type OrderRecord struct {
ID primitive.ObjectID `json:"id"` // ID
SumDate time.Time `json:"sumDate"` //日期
Type statordermod.OrderType `json:"type"` //订单类型
Channel string `json:"channel"` //渠道
OrderData
CreatedAt time.Time `json:"createdAt"` //文档创建时间
}
type OrderPage struct {
Total int64 `json:"total"`
List []OrderRecord `json:"list"`
}
type OrderChannelMatch = statordermod.ChannelMatch
type OrderTypeMatch = statordermod.TypeMatch
type OrderSumDateGTEAndLTMatch = statordermod.SumDateGTEAndLTMatch
var Order_Sort_SumDate_n1 = statordermod.Sort_SumDate_n1
func OrderPages(skip, limit int64,
channelMatch OrderChannelMatch,
typeMatch OrderTypeMatch,
sumDateGTEAndLTMatch OrderSumDateGTEAndLTMatch,
) (OrderPage, error) {
matList := []pageopt.Matcher{
channelMatch.New(),
typeMatch.New(),
sumDateGTEAndLTMatch.New(),
}
list, err := statordermod.List(Order_Sort_SumDate_n1, &skip, &limit, matList...)
if err != nil {
return OrderPage{}, err
}
recordList := make([]OrderRecord, 0, len(list))
for _, v := range list {
record := OrderRecord{
ID: v.ID,
SumDate: v.SumDate,
Type: v.Type,
Channel: v.Channel,
CreatedAt: v.CreatedAt,
}
record.From(v.Items)
record.BaiYuan()
recordList = append(recordList, record)
}
count, err := statordermod.Count(matList...)
if err != nil {
return OrderPage{}, err
}
return OrderPage{
Total: count,
List: recordList,
}, nil
}
type RchgordChannelMatch = rchgordmod.ChannelMatch
type RchgordCreatedAtGTEAndLTMatch = rchgordmod.CreatedAtGTEAndLTMatch
func RechargeSucRateMap(sumDate time.Time, channel string) (map[int64]float64, error) {
locDayRange := timerange.LocDayRange(sumDate)
return rchgordmod.SuccessRateMap(channel, locDayRange.Head, locDayRange.Tail, 15)
}
type DataStruct struct {
SumData string `json:"sumData"` //统计日期
VIPRecharge int64 `json:"vipRecharge"` //会员卡充值
CoinRecharge int64 `json:"coinRecharge"` //金币充值
LoufengTrade int64 `json:"loufengTrade"` //楼凤交易充值
VipTrande map[string]*VipTrande `json:"vipTrande"`
NewUser int64 `json:"newCount"` //新增用户
}
type VipTrande struct {
ID primitive.ObjectID `json:"id"`
Name string `json:"name"`
Count int64 `json:"count"` //购买次数
Amount int64 `json:"amount"` //购买金额
}
func getDateString(t time.Time) string {
return t.Format("20060102")
}
func DataStat(start, end time.Time) (res []*DataStruct, err error, vipTitle []string) {
m := make(map[string]*DataStruct)
productMap := make(map[primitive.ObjectID]productmod.ProductWeb)
products, err := productmod.FindMany()
if err != nil {
return
}
vipTitle = make([]string, 0)
for i := range products {
productMap[products[i].ID] = products[i]
vipTitle = append(vipTitle, products[i].Name)
}
vipTitle = append(vipTitle, "未知")
data, err := prdcthsomod.FindMany(start, end, options.Find())
if err != nil {
return
}
for _, v := range data {
key := getDateString(v.CreatedAt)
name := productMap[v.ProductID].Name
if name == "" {
name = "未知"
}
if _, ok := m[key]; ok {
if _, ok2 := m[key].VipTrande[name]; ok2 {
m[key].VipTrande[name].Count += 1
m[key].VipTrande[name].Amount += v.Amount
} else {
m[key].VipTrande[name] = &VipTrande{
Name: name,
Count: 1,
Amount: v.Income + v.Amount,
}
}
} else {
vipTrandeM := make(map[string]*VipTrande)
m[key] = &DataStruct{
SumData: key,
VipTrande: vipTrandeM,
}
m[key].VipTrande[name] = &VipTrande{
Name: name,
Count: 1,
Amount: v.Income + v.Amount,
}
}
}
orders, err := rchgordmod.GetOrderByTime(start, end)
if err != nil {
return
}
for _, v := range orders {
key := getDateString(v.CreatedAt)
if _, ok := m[key]; ok {
} else {
m[key] = &DataStruct{
SumData: key,
}
}
if v.VipID.IsZero() {
m[key].CoinRecharge += v.PayMoney
} else {
m[key].VIPRecharge += v.PayMoney
}
}
trans, err := txnmod.TransStat(start, end)
if err != nil {
return
}
for _, v := range trans {
key := getDateString(v.CreatedAt)
if _, ok := m[key]; ok {
} else {
m[key] = &DataStruct{
SumData: key,
}
}
m[key].LoufengTrade += int64(v.ActualAmount)
}
userStat, err := usermod.FindByCreateTime(start, end)
if err != nil {
return
}
for _, v := range userStat {
key := getDateString(v.CreatedAt)
if _, ok := m[key]; ok {
} else {
m[key] = &DataStruct{
SumData: key,
}
}
m[key].NewUser += 1
}
res = make([]*DataStruct, 0)
for start.Before(end) {
key := getDateString(start)
if _, ok := m[key]; ok {
} else {
m[key] = &DataStruct{
SumData: key,
}
}
res = append(res, m[key])
start = start.Add(time.Hour * 24)
}
return
}
type PayVidStatInfo struct {
SumData string `json:"sumData"` //统计日期
ShortVidAmount int64 `json:"shortVidAmount"` //短视频销售额
ShortVidCount int64 `json:"ShortVidCount"` //短视频销售数量
LongVidAmount int64 `json:"longVidAmount"` //短视频销售额
LongVidCount int64 `json:"longVidCount"` //短视频销售数量
}
func PayVidStat(start, end time.Time) (res []*PayVidStatInfo, err error) {
m := make(map[string]*PayVidStatInfo)
payVidLogs, err := payvidlgmod.GetPayVidLogsByTime(start, end)
if err != nil {
return
}
vids := make([]primitive.ObjectID, 0)
for i := range payVidLogs {
vids = append(vids, payVidLogs[i].VideoID)
}
longVid, err := vidmod.FindShortVidByIDs(vids)
if err != nil {
return
}
longVidMap := make(map[primitive.ObjectID]int)
for i := range longVid {
longVidMap[longVid[i]] = 1
}
for _, v := range payVidLogs {
key := getDateString(v.CreatedAt)
if _, ok := m[key]; ok {
} else {
m[key] = &PayVidStatInfo{
SumData: key,
}
}
_, ok := longVidMap[v.VideoID]
if ok {
m[key].LongVidAmount += v.PayMoney
m[key].LongVidCount += 1
} else {
m[key].ShortVidAmount += v.PayMoney
m[key].ShortVidCount += 1
}
}
res = make([]*PayVidStatInfo, 0)
for start.Before(end) {
key := getDateString(start)
if _, ok := m[key]; ok {
} else {
m[key] = &PayVidStatInfo{
SumData: key,
}
}
res = append(res, m[key])
start = start.Add(time.Hour * 24)
}
return
}