✨ added apis and optimized table structures
This commit is contained in:
@@ -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,
|
||||
|
@@ -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 {
|
||||
|
75
app/auth/api/internal/logic/share/query_share_info_logic.go
Normal file
75
app/auth/api/internal/logic/share/query_share_info_logic.go
Normal 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
|
||||
}
|
@@ -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
|
||||
}
|
@@ -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
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user