mirror of
https://github.com/wgh136/nysoure.git
synced 2025-09-27 12:17:24 +00:00
Add statistics.
This commit is contained in:
@@ -5,6 +5,8 @@ export interface User {
|
|||||||
avatar_path: string;
|
avatar_path: string;
|
||||||
is_admin: boolean;
|
is_admin: boolean;
|
||||||
can_upload: boolean;
|
can_upload: boolean;
|
||||||
|
uploads_count: number;
|
||||||
|
comments_count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserWithToken extends User {
|
export interface UserWithToken extends User {
|
||||||
@@ -62,6 +64,8 @@ export interface ResourceDetails {
|
|||||||
images: Image[];
|
images: Image[];
|
||||||
files: RFile[];
|
files: RFile[];
|
||||||
author: User;
|
author: User;
|
||||||
|
views: number;
|
||||||
|
downloads: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Storage {
|
export interface Storage {
|
||||||
|
@@ -1,15 +1,30 @@
|
|||||||
package dao
|
package dao
|
||||||
|
|
||||||
import "nysoure/server/model"
|
import (
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"nysoure/server/model"
|
||||||
|
)
|
||||||
|
|
||||||
func CreateComment(content string, userID uint, resourceID uint) (model.Comment, error) {
|
func CreateComment(content string, userID uint, resourceID uint) (model.Comment, error) {
|
||||||
c := model.Comment{
|
var comment model.Comment
|
||||||
Content: content,
|
err := db.Transaction(func(tx *gorm.DB) error {
|
||||||
UserID: userID,
|
comment = model.Comment{
|
||||||
ResourceID: resourceID,
|
Content: content,
|
||||||
|
UserID: userID,
|
||||||
|
ResourceID: resourceID,
|
||||||
|
}
|
||||||
|
if err := tx.Create(&comment).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := tx.Model(&model.User{}).Where("id = ?", userID).Update("comments_count", gorm.Expr("comments_count + 1")).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return model.Comment{}, err
|
||||||
}
|
}
|
||||||
err := db.Save(&c).Error
|
return comment, nil
|
||||||
return c, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCommentByResourceID(resourceID uint, page, pageSize int) ([]model.Comment, int, error) {
|
func GetCommentByResourceID(resourceID uint, page, pageSize int) ([]model.Comment, int, error) {
|
||||||
|
@@ -9,8 +9,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func CreateResource(r model.Resource) (model.Resource, error) {
|
func CreateResource(r model.Resource) (model.Resource, error) {
|
||||||
// Create a new resource in the database
|
err := db.Transaction(func(tx *gorm.DB) error {
|
||||||
if err := db.Create(&r).Error; err != nil {
|
err := tx.Create(&r).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := tx.Model(&model.User{}).Where("id = ?", r.UserID).Update("uploads_count", gorm.Expr("uploads_count + ?", 1)).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
return model.Resource{}, err
|
return model.Resource{}, err
|
||||||
}
|
}
|
||||||
return r, nil
|
return r, nil
|
||||||
@@ -55,13 +64,22 @@ func UpdateResource(r model.Resource) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func DeleteResource(id uint) error {
|
func DeleteResource(id uint) error {
|
||||||
// Delete a resource from the database
|
return db.Transaction(func(tx *gorm.DB) error {
|
||||||
r := model.Resource{}
|
var r model.Resource
|
||||||
r.ID = id
|
if err := tx.Where("id = ?", id).First(&r).Error; err != nil {
|
||||||
if err := db.Delete(&r).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return err
|
return model.NewNotFoundError("Resource not found")
|
||||||
}
|
}
|
||||||
return nil
|
return err
|
||||||
|
}
|
||||||
|
if err := tx.Model(&model.User{}).Where("id = ?", r.UserID).Update("uploads_count", gorm.Expr("uploads_count - ?", 1)).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := tx.Delete(&r).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Search(query string, page, pageSize int) ([]model.Resource, int, error) {
|
func Search(query string, page, pageSize int) ([]model.Resource, int, error) {
|
||||||
@@ -178,3 +196,17 @@ func ExistsResource(id uint) (bool, error) {
|
|||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AddResourceViewCount(id uint) error {
|
||||||
|
if err := db.Model(&model.Resource{}).Where("id = ?", id).Update("views", gorm.Expr("views + ?", 1)).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddResourceDownloadCount(id uint) error {
|
||||||
|
if err := db.Model(&model.Resource{}).Where("id = ?", id).Update("downloads", gorm.Expr("downloads + ?", 1)).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@@ -61,6 +61,9 @@ func GetUserByUsername(username string) (model.User, error) {
|
|||||||
func GetUserByID(id uint) (model.User, error) {
|
func GetUserByID(id uint) (model.User, error) {
|
||||||
var user model.User
|
var user model.User
|
||||||
if err := db.First(&user, id).Error; err != nil {
|
if err := db.First(&user, id).Error; err != nil {
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return user, model.NewNotFoundError("User not found")
|
||||||
|
}
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
return user, nil
|
return user, nil
|
||||||
|
@@ -16,6 +16,8 @@ type Resource struct {
|
|||||||
Files []File `gorm:"foreignKey:ResourceID"`
|
Files []File `gorm:"foreignKey:ResourceID"`
|
||||||
UserID uint
|
UserID uint
|
||||||
User User
|
User User
|
||||||
|
Views uint
|
||||||
|
Downloads uint
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResourceView struct {
|
type ResourceView struct {
|
||||||
@@ -37,6 +39,8 @@ type ResourceDetailView struct {
|
|||||||
Images []ImageView `json:"images"`
|
Images []ImageView `json:"images"`
|
||||||
Files []FileView `json:"files"`
|
Files []FileView `json:"files"`
|
||||||
Author UserView `json:"author"`
|
Author UserView `json:"author"`
|
||||||
|
Views uint `json:"views"`
|
||||||
|
Downloads uint `json:"downloads"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resource) ToView() ResourceView {
|
func (r *Resource) ToView() ResourceView {
|
||||||
@@ -85,5 +89,7 @@ func (r *Resource) ToDetailView() ResourceDetailView {
|
|||||||
Images: images,
|
Images: images,
|
||||||
Files: files,
|
Files: files,
|
||||||
Author: r.User.ToView(),
|
Author: r.User.ToView(),
|
||||||
|
Views: r.Views,
|
||||||
|
Downloads: r.Downloads,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,16 +13,20 @@ type User struct {
|
|||||||
IsAdmin bool
|
IsAdmin bool
|
||||||
CanUpload bool
|
CanUpload bool
|
||||||
AvatarVersion int
|
AvatarVersion int
|
||||||
|
UploadsCount int
|
||||||
|
CommentsCount int
|
||||||
Resources []Resource `gorm:"foreignKey:UserID"`
|
Resources []Resource `gorm:"foreignKey:UserID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserView struct {
|
type UserView struct {
|
||||||
ID uint `json:"id"`
|
ID uint `json:"id"`
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
AvatarPath string `json:"avatar_path"`
|
AvatarPath string `json:"avatar_path"`
|
||||||
IsAdmin bool `json:"is_admin"`
|
IsAdmin bool `json:"is_admin"`
|
||||||
CanUpload bool `json:"can_upload"`
|
CanUpload bool `json:"can_upload"`
|
||||||
|
UploadsCount int `json:"uploads_count"`
|
||||||
|
CommentsCount int `json:"comments_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserViewWithToken struct {
|
type UserViewWithToken struct {
|
||||||
@@ -32,12 +36,14 @@ type UserViewWithToken struct {
|
|||||||
|
|
||||||
func (u User) ToView() UserView {
|
func (u User) ToView() UserView {
|
||||||
return UserView{
|
return UserView{
|
||||||
ID: u.ID,
|
ID: u.ID,
|
||||||
Username: u.Username,
|
Username: u.Username,
|
||||||
CreatedAt: u.CreatedAt,
|
CreatedAt: u.CreatedAt,
|
||||||
AvatarPath: fmt.Sprintf("/api/user/avatar/%d?v=%d", u.ID, u.AvatarVersion),
|
AvatarPath: fmt.Sprintf("/api/user/avatar/%d?v=%d", u.ID, u.AvatarVersion),
|
||||||
IsAdmin: u.IsAdmin,
|
IsAdmin: u.IsAdmin,
|
||||||
CanUpload: u.CanUpload || u.IsAdmin,
|
CanUpload: u.CanUpload || u.IsAdmin,
|
||||||
|
UploadsCount: u.UploadsCount,
|
||||||
|
CommentsCount: u.CommentsCount,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -379,6 +379,7 @@ func DownloadFile(fid string) (string, string, error) {
|
|||||||
|
|
||||||
if file.StorageID == nil {
|
if file.StorageID == nil {
|
||||||
if file.RedirectUrl != "" {
|
if file.RedirectUrl != "" {
|
||||||
|
_ = dao.AddResourceDownloadCount(file.ResourceID)
|
||||||
return file.RedirectUrl, file.Filename, nil
|
return file.RedirectUrl, file.Filename, nil
|
||||||
}
|
}
|
||||||
return "", "", model.NewRequestError("file is not available")
|
return "", "", model.NewRequestError("file is not available")
|
||||||
@@ -396,5 +397,7 @@ func DownloadFile(fid string) (string, string, error) {
|
|||||||
|
|
||||||
path, err := iStorage.Download(file.StorageKey, file.Filename)
|
path, err := iStorage.Download(file.StorageKey, file.Filename)
|
||||||
|
|
||||||
|
_ = dao.AddResourceDownloadCount(file.ResourceID)
|
||||||
|
|
||||||
return path, file.Filename, err
|
return path, file.Filename, err
|
||||||
}
|
}
|
||||||
|
@@ -56,6 +56,7 @@ func CreateResource(uid uint, params *ResourceCreateParams) (uint, error) {
|
|||||||
|
|
||||||
func GetResource(id uint) (*model.ResourceDetailView, error) {
|
func GetResource(id uint) (*model.ResourceDetailView, error) {
|
||||||
r, err := dao.GetResourceByID(id)
|
r, err := dao.GetResourceByID(id)
|
||||||
|
_ = dao.AddResourceViewCount(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user