added apis and optimized table structures

This commit is contained in:
2025-02-22 23:38:36 +08:00
parent db4c59f6f6
commit 737a367677
49 changed files with 1753 additions and 1377 deletions

View File

@@ -35,7 +35,7 @@ func (l *ListShareRecordLogic) ListShareRecord(req *types.ShareRecordListRequest
var recordList []types.ShareRecord
query := storageShare.
Select(storageShare.ID,
storageShare.ShareCode,
storageShare.InviteCode,
storageShare.VisitLimit,
storageShare.AccessPassword,
storageShare.ValidityPeriod,

View File

@@ -41,7 +41,7 @@ func (l *QueryShareImageLogic) QueryShareImage(req *types.QueryShareImageRequest
return nil, errors.New("user_id not found")
}
// 获取分享记录
cacheKey := constant.ImageSharePrefix + req.ShareCode
cacheKey := constant.ImageSharePrefix + req.InviteCode
shareData, err := l.svcCtx.RedisClient.Get(l.ctx, cacheKey).Result()
if err != nil {
if errors.Is(err, redis.Nil) {
@@ -66,7 +66,7 @@ func (l *QueryShareImageLogic) QueryShareImage(req *types.QueryShareImageRequest
// 检查访问限制
if storageShare.VisitLimit > 0 {
err = l.incrementVisitCount(req.ShareCode, storageShare.VisitLimit)
err = l.incrementVisitCount(req.InviteCode, storageShare.VisitLimit)
if err != nil {
return nil, err
}
@@ -79,7 +79,7 @@ func (l *QueryShareImageLogic) QueryShareImage(req *types.QueryShareImageRequest
}
// 生成缓存键(在验证通过后)
resultCacheKey := constant.ImageListPrefix + req.ShareCode + ":" + req.AccessPassword
resultCacheKey := constant.ImageCachePrefix + storageShare.UserID + ":share:" + req.InviteCode
// 尝试从缓存中获取结果
cachedResult, err := l.svcCtx.RedisClient.Get(l.ctx, resultCacheKey).Result()
@@ -131,7 +131,7 @@ func (l *QueryShareImageLogic) queryShareImageFromSource(storageShare *model.Sca
storageThumb.ThumbW,
storageThumb.ThumbH,
storageThumb.ThumbSize).
LeftJoin(storageThumb, storageInfo.ThumbID.EqCol(storageThumb.ID)).
LeftJoin(storageThumb, storageInfo.ID.EqCol(storageThumb.InfoID)).
Where(
storageInfo.Type.Eq(constant.ImageTypeShared),
storageInfo.AlbumID.Eq(storageShare.AlbumID)).
@@ -175,8 +175,8 @@ func (l *QueryShareImageLogic) queryShareImageFromSource(storageShare *model.Sca
ResultList = append(ResultList, types.ShareImageListMeta{
ID: imgInfo.ID,
FileName: imgInfo.FileName,
ThumbH: imgInfo.ThumbH,
ThumbW: imgInfo.ThumbW,
Height: imgInfo.ThumbH,
Width: imgInfo.ThumbW,
ThumbSize: imgInfo.ThumbSize,
CreatedAt: imgInfo.CreatedAt.Format(constant.TimeFormat),
URL: ossURL,
@@ -192,7 +192,7 @@ func (l *QueryShareImageLogic) queryShareImageFromSource(storageShare *model.Sca
}
return &types.QueryShareImageResponse{
List: ResultList}, nil
Records: ResultList}, nil
}
func (l *QueryShareImageLogic) recordUserVisit(shareID int64, userID string) error {

View File

@@ -0,0 +1,75 @@
package share
import (
"context"
"errors"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type QueryShareInfoLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewQueryShareInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryShareInfoLogic {
return &QueryShareInfoLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *QueryShareInfoLogic) QueryShareInfo(req *types.QueryShareInfoRequest) (resp *types.ShareInfoResponse, err error) {
uid, ok := l.ctx.Value("user_id").(string)
if !ok {
return nil, errors.New("user_id not found")
}
storageShare := l.svcCtx.DB.ScaStorageShare
storageAlbum := l.svcCtx.DB.ScaStorageAlbum
shareVisit := l.svcCtx.DB.ScaStorageShareVisit
authUser := l.svcCtx.DB.ScaAuthUser
var shareInfo types.ShareInfoResponse
err = storageShare.Select(
storageShare.ID,
storageShare.VisitLimit,
storageShare.InviteCode,
storageShare.ExpireTime,
storageShare.CreatedAt,
storageAlbum.CoverImage,
storageAlbum.AlbumName,
storageShare.ImageCount,
shareVisit.Views.As("visit_count"),
shareVisit.UserID.Count().As("viewer_count"),
authUser.Avatar.As("sharer_avatar"),
authUser.Nickname.As("sharer_name")).
LeftJoin(storageAlbum, storageShare.AlbumID.EqCol(storageAlbum.ID)).
Join(shareVisit, storageShare.ID.EqCol(shareVisit.ShareID)).
LeftJoin(authUser, storageShare.UserID.EqCol(authUser.UID)).
Where(
storageShare.InviteCode.Eq(req.InviteCode),
shareVisit.UserID.Eq(uid)).
Group(
storageShare.ID,
storageShare.VisitLimit,
storageShare.InviteCode,
storageShare.ExpireTime,
storageShare.CreatedAt,
storageAlbum.CoverImage,
storageShare.ImageCount,
storageAlbum.AlbumName,
shareVisit.Views,
authUser.Avatar,
authUser.Nickname).
Scan(&shareInfo)
if err != nil {
return nil, err
}
return &shareInfo, nil
}

View File

@@ -0,0 +1,80 @@
package share
import (
"context"
"errors"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"time"
"github.com/zeromicro/go-zero/core/logx"
)
type QueryShareOverviewLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewQueryShareOverviewLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryShareOverviewLogic {
return &QueryShareOverviewLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *QueryShareOverviewLogic) QueryShareOverview() (resp *types.ShareOverviewResponse, err error) {
uid, ok := l.ctx.Value("user_id").(string)
if !ok {
return nil, errors.New("user_id not found")
}
storageShare := l.svcCtx.DB.ScaStorageShare
shareVisit := l.svcCtx.DB.ScaStorageShareVisit
// 统计所有数据
var totalResult struct {
TotalCount int64
TotalViews int64
TotalUsers int64
}
err = storageShare.Select(
storageShare.ID.Count().As("total_count"),
shareVisit.Views.Sum().As("total_views"),
shareVisit.UserID.Distinct().Count().As("total_users"),
).
Join(shareVisit, storageShare.ID.EqCol(shareVisit.ShareID)).
Where(storageShare.UserID.Eq(uid)).
Scan(&totalResult)
if err != nil {
return nil, err
}
// 统计当天数据
var dailyResult struct {
DailyCount int64
DailyViews int64
DailyUsers int64
}
err = storageShare.Select(
storageShare.ID.Count().As("daily_count"),
shareVisit.Views.Sum().As("daily_views"),
shareVisit.UserID.Distinct().Count().As("daily_users"),
).
Join(shareVisit, storageShare.ID.EqCol(shareVisit.ShareID)).
Where(storageShare.UserID.Eq(uid),
shareVisit.CreatedAt.Gte(time.Now().Truncate(24*time.Hour))).
Scan(&dailyResult)
if err != nil {
return nil, err
}
// 合并结果到 ShareOverviewResponse
response := types.ShareOverviewResponse{
VisitCount: totalResult.TotalViews, // 总访问量
VisitCountToday: dailyResult.DailyViews, // 当天访问量
ViewerCount: totalResult.TotalUsers, // 总独立用户数
ViewerCountToday: dailyResult.DailyUsers, // 当天独立用户数
PublishCount: totalResult.TotalCount, // 总发布量
PublishCountToday: dailyResult.DailyCount, // 当天发布量
}
return &response, nil
}

View File

@@ -94,12 +94,13 @@ func (l *UploadShareImageLogic) UploadShareImage(req *types.ShareImageRequest) (
storageShare := model.ScaStorageShare{
UserID: uid,
AlbumID: album.ID,
ShareCode: kgo.SimpleUuid(),
InviteCode: kgo.SimpleUuid(),
Status: 0,
AccessPassword: req.AccessPassword,
VisitLimit: req.AccessLimit,
ValidityPeriod: int64(duration),
ExpireTime: expiryTime,
ImageCount: int64(len(req.Images)),
}
err = tx.ScaStorageShare.Create(&storageShare)
if err != nil {
@@ -112,7 +113,7 @@ func (l *UploadShareImageLogic) UploadShareImage(req *types.ShareImageRequest) (
tx.Rollback()
return "", err
}
cacheKey := constant.ImageSharePrefix + storageShare.ShareCode
cacheKey := constant.ImageSharePrefix + storageShare.InviteCode
err = l.svcCtx.RedisClient.Set(l.ctx, cacheKey, marshal, time.Duration(duration)*time.Hour*24).Err()
if err != nil {
tx.Rollback()
@@ -124,56 +125,10 @@ func (l *UploadShareImageLogic) UploadShareImage(req *types.ShareImageRequest) (
logx.Errorf("Transaction commit failed: %v", err)
return "", err
}
return storageShare.ShareCode, nil
return storageShare.InviteCode, nil
}
func (l *UploadShareImageLogic) uploadImageAndRecord(tx *query.QueryTx, uid string, album model.ScaStorageAlbum, img types.ShareImageMeta, req *types.ShareImageRequest) error {
// 上传缩略图到 Minio
thumbnail, err := base64.StdEncoding.DecodeString(img.Thumbnail)
if err != nil {
return fmt.Errorf("base64 decode failed: %v", err)
}
thumbObjectKey := path.Join(
uid,
time.Now().Format("2006/01"),
l.classifyFile(img.FileType),
fmt.Sprintf("%s_%s.jpg", time.Now().Format("20060102150405"), kgo.SimpleUuid()),
)
exists, err := l.svcCtx.MinioClient.BucketExists(l.ctx, constant.ThumbnailBucketName)
if err != nil || !exists {
err = l.svcCtx.MinioClient.MakeBucket(l.ctx, constant.ThumbnailBucketName, minio.MakeBucketOptions{Region: "us-east-1", ObjectLocking: true})
if err != nil {
logx.Errorf("Failed to create MinIO bucket: %v", err)
return err
}
}
_, err = l.svcCtx.MinioClient.PutObject(
l.ctx,
constant.ThumbnailBucketName,
thumbObjectKey,
bytes.NewReader(thumbnail),
int64(len(thumbnail)),
minio.PutObjectOptions{
ContentType: "image/jpeg",
},
)
if err != nil {
logx.Errorf("Failed to upload MinIO object: %v", err)
return err
}
// 记录缩略图
thumbRecord := model.ScaStorageThumb{
UserID: uid,
ThumbPath: thumbObjectKey,
ThumbW: img.ThumbW,
ThumbH: img.ThumbH,
ThumbSize: float64(len(thumbnail)),
}
err = tx.ScaStorageThumb.Create(&thumbRecord)
if err != nil {
return err
}
// 上传原始图片到用户的存储桶
originImage, err := base64.StdEncoding.DecodeString(img.OriginImage)
@@ -211,24 +166,72 @@ func (l *UploadShareImageLogic) uploadImageAndRecord(tx *query.QueryTx, uid stri
// 记录原始图片信息
imageRecord := model.ScaStorageInfo{
UserID: uid,
Provider: req.Provider,
Bucket: req.Bucket,
Path: originObjectKey,
FileName: img.FileName,
FileSize: strconv.Itoa(size),
FileType: img.FileType,
Width: float64(width),
Height: float64(height),
Type: constant.ImageTypeShared,
AlbumID: album.ID,
ThumbID: thumbRecord.ID,
UserID: uid,
Provider: req.Provider,
Bucket: req.Bucket,
Path: originObjectKey,
FileName: img.FileName,
FileSize: strconv.Itoa(size),
FileType: img.FileType,
Width: float64(width),
Height: float64(height),
Type: constant.ImageTypeShared,
AlbumID: album.ID,
IsDisplayed: 1,
}
err = tx.ScaStorageInfo.Create(&imageRecord)
if err != nil {
return err
}
// 上传缩略图到 Minio
thumbnail, err := base64.StdEncoding.DecodeString(img.Thumbnail)
if err != nil {
return fmt.Errorf("base64 decode failed: %v", err)
}
thumbObjectKey := path.Join(
uid,
time.Now().Format("2006/01"),
l.classifyFile(img.FileType),
fmt.Sprintf("%s_%s.jpg", time.Now().Format("20060102150405"), kgo.SimpleUuid()),
)
exists, err := l.svcCtx.MinioClient.BucketExists(l.ctx, constant.ThumbnailBucketName)
if err != nil || !exists {
err = l.svcCtx.MinioClient.MakeBucket(l.ctx, constant.ThumbnailBucketName, minio.MakeBucketOptions{Region: "us-east-1", ObjectLocking: true})
if err != nil {
logx.Errorf("Failed to create MinIO bucket: %v", err)
return err
}
}
_, err = l.svcCtx.MinioClient.PutObject(
l.ctx,
constant.ThumbnailBucketName,
thumbObjectKey,
bytes.NewReader(thumbnail),
int64(len(thumbnail)),
minio.PutObjectOptions{
ContentType: "image/jpeg",
},
)
if err != nil {
logx.Errorf("Failed to upload MinIO object: %v", err)
return err
}
// 记录缩略图
thumbRecord := model.ScaStorageThumb{
InfoID: imageRecord.ID,
UserID: uid,
ThumbPath: thumbObjectKey,
ThumbW: img.ThumbW,
ThumbH: img.ThumbH,
ThumbSize: float64(len(thumbnail)),
}
err = tx.ScaStorageThumb.Create(&thumbRecord)
if err != nil {
return err
}
return nil
}