You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
5.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package model
import (
"fmt"
v1 "moredoc/api/v1"
"time"
"go.uber.org/zap"
"gorm.io/gorm"
)
type Download struct {
Id int64 `form:"id" json:"id,omitempty" gorm:"primaryKey;autoIncrement;column:id;comment:;"`
UserId int64 `form:"user_id" json:"user_id,omitempty" gorm:"column:user_id;type:bigint(20);size:20;default:0;index:idx_user_id;comment:下载文档的用户ID;"`
DocumentId int64 `form:"document_id" json:"document_id,omitempty" gorm:"column:document_id;type:bigint(20);size:20;index:idx_document_id;default:0;comment:被下载的文档ID;"`
Ip string `form:"ip" json:"ip,omitempty" gorm:"column:ip;type:varchar(64);size:64;index:idx_ip;comment:下载文档的用户IP;"`
IsPay bool `form:"is_pay" json:"is_pay,omitempty" gorm:"column:is_pay;type:tinyint(1);size:1;default:0;comment:是否付费下载;"`
CreatedAt *time.Time `form:"created_at" json:"created_at,omitempty" gorm:"column:created_at;type:datetime;comment:创建时间;index:idx_created_at"`
UpdatedAt *time.Time `form:"updated_at" json:"updated_at,omitempty" gorm:"column:updated_at;type:datetime;comment:更新时间;"`
}
func (Download) TableName() string {
return tablePrefix + "download"
}
// CreateDownload 创建Download
func (m *DBModel) CreateDownload(download *Download) (err error) {
tx := m.db.Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
err = tx.Create(download).Error
if err != nil {
m.logger.Error("CreateDownload", zap.Error(err))
return
}
err = tx.Model(&Document{}).Where("id = ?", download.DocumentId).Update("download_count", gorm.Expr("download_count + ?", 1)).Error
if err != nil {
m.logger.Error("CreateDownload", zap.Error(err))
return
}
doc, _ := m.GetDocument(download.DocumentId, "id", "user_id", "price")
if download.IsPay && doc.Price > 0 && download.UserId > 0 {
// 下载该文档的用户扣除积分
err = tx.Model(&User{}).Where("id = ?", download.UserId).Update("credit_count", gorm.Expr("credit_count - ?", doc.Price)).Error
if err != nil {
m.logger.Error("CreateDownload", zap.Error(err))
return
}
// 文档的作者增加积分
err = tx.Model(&User{}).Where("id = ?", doc.UserId).Update("credit_count", gorm.Expr("credit_count + ?", doc.Price)).Error
if err != nil {
m.logger.Error("CreateDownload", zap.Error(err))
return
}
}
return
}
// GetDownload 根据id获取Download
func (m *DBModel) GetDownload(id interface{}, fields ...string) (download Download, err error) {
db := m.db
fields = m.FilterValidFields(Download{}.TableName(), fields...)
if len(fields) > 0 {
db = db.Select(fields)
}
err = db.Where("id = ?", id).First(&download).Error
return
}
type OptionGetDownloadList struct {
Page int
Size int
WithCount bool // 是否返回总数
Ids []interface{} // id列表
QueryIn map[string][]interface{} // map[field][]{value1,value2,...}
}
// GetDownloadList 获取Download列表
func (m *DBModel) GetDownloadList(opt *OptionGetDownloadList) (downloadList []*v1.Download, total int64, err error) {
var (
tableDownload = Download{}.TableName()
tableDocument = Document{}.TableName()
)
db := m.db.Model(&Download{})
db = m.generateQueryIn(db, tableDownload+" "+tableDownload /* 加上表别名,防止字段冲突 */, opt.QueryIn)
if len(opt.Ids) > 0 {
db = db.Where(fmt.Sprintf("%s.id in (?)", tableDownload), opt.Ids)
}
db = db.Joins(
fmt.Sprintf(
"left join %s on %s.document_id = %s.id",
tableDocument, tableDownload, tableDocument,
)).
Where(fmt.Sprintf("%s.id > ?", tableDocument), 0)
if opt.WithCount {
err = db.Count(&total).Error
if err != nil {
m.logger.Error("GetDownloadList", zap.Error(err))
return
}
}
// size 为了避免字段冲突加上了后缀_即 size_
db = db.Select(fmt.Sprintf("%s.*, %s.*, %s.size as size_", tableDocument, tableDownload, tableDocument))
db = db.Order(fmt.Sprintf("%s.id desc", tableDownload))
db = db.Offset((opt.Page - 1) * opt.Size).Limit(opt.Size)
err = db.Find(&downloadList).Error
if err != nil && err != gorm.ErrRecordNotFound {
m.logger.Error("GetDownloadList", zap.Error(err))
}
return
}
// CanIFreeDownload 判断用户是否可以免费下载
// 最后一次付费下载时间 + 免费下载时长 > 当前时间
func (m *DBModel) CanIFreeDownload(userId, documentId int64) bool {
var download Download
m.db.Where("user_id = ? and document_id = ? and is_pay = ?", userId, documentId, 1).Last(&download)
m.logger.Debug("CanIFreeDownload", zap.Any("Last Download", download))
if download.Id == 0 {
return false
}
cfg := m.GetConfigOfDownload(ConfigDownloadFreeDownloadDuration)
m.logger.Debug("CanIFreeDownload", zap.Int32("FreeDownloadDuration", cfg.FreeDownloadDuration))
if cfg.FreeDownloadDuration <= 0 {
return true
}
m.logger.Debug("CanIFreeDownload", zap.Any("CreatedAt", download.CreatedAt), zap.Time("Now", time.Now()), zap.Time("After", download.CreatedAt.Add(time.Duration(cfg.FreeDownloadDuration)*time.Hour*24)))
return download.CreatedAt.Add(time.Duration(cfg.FreeDownloadDuration) * time.Hour * 24).After(time.Now())
}
// CountDownloadToday 统计用户今日下载次数
func (m *DBModel) CountDownloadTodayForUser(userId int64) (total int64) {
if userId == 0 {
return
}
err := m.db.Model(&Download{}).Where("user_id = ?", userId).Where("created_at >= ?", time.Now().Format("2006-01-02")).Count(&total).Error
if err != nil {
m.logger.Error("CountDownloadToday", zap.Error(err))
}
return
}
// CountDownloadToday 统计IP今日下载次数
func (m *DBModel) CountDownloadTodayForIP(ip string) (total int64) {
if ip == "" {
return
}
err := m.db.Model(&Download{}).Where("ip = ?", ip).Where("created_at >= ?", time.Now().Format("2006-01-02")).Count(&total).Error
if err != nil {
m.logger.Error("CountDownloadTodayForIP", zap.Error(err))
}
return
}