🚧 developing...
This commit is contained in:
@@ -403,8 +403,8 @@ type (
|
|||||||
)
|
)
|
||||||
|
|
||||||
@server (
|
@server (
|
||||||
group: upscale // 微服务分组
|
group: phone // 微服务分组
|
||||||
prefix: /api/auth/upscale // 微服务前缀
|
prefix: /api/auth/phone // 微服务前缀
|
||||||
timeout: 10s // 超时时间
|
timeout: 10s // 超时时间
|
||||||
maxBytes: 10485760 // 最大请求大小
|
maxBytes: 10485760 // 最大请求大小
|
||||||
signature: false // 是否开启签名验证
|
signature: false // 是否开启签名验证
|
||||||
@@ -414,7 +414,7 @@ type (
|
|||||||
)
|
)
|
||||||
service auth {
|
service auth {
|
||||||
@handler uploadImage
|
@handler uploadImage
|
||||||
post /phone/upload (UploadRequest)
|
post /upload (UploadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 文件上传配置请求参数
|
// 文件上传配置请求参数
|
||||||
@@ -529,6 +529,10 @@ type (
|
|||||||
AllImageListResponse {
|
AllImageListResponse {
|
||||||
records []AllImageDetail `json:"records"`
|
records []AllImageDetail `json:"records"`
|
||||||
}
|
}
|
||||||
|
RecentListRequest {
|
||||||
|
Provider string `json:"provider"`
|
||||||
|
Bucket string `json:"bucket"`
|
||||||
|
}
|
||||||
// 最近上传图片列表请求参数
|
// 最近上传图片列表请求参数
|
||||||
RecentListResponse {
|
RecentListResponse {
|
||||||
records []AllImageDetail `json:"records"`
|
records []AllImageDetail `json:"records"`
|
||||||
@@ -626,6 +630,19 @@ type (
|
|||||||
Used string `json:"used"`
|
Used string `json:"used"`
|
||||||
Percentage float64 `json:"percentage"`
|
Percentage float64 `json:"percentage"`
|
||||||
}
|
}
|
||||||
|
ShareAlbumRequest {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
ExpireDate string `json:"expire_date"`
|
||||||
|
AccessLimit int64 `json:"access_limit,omitempty"`
|
||||||
|
AccessPassword string `json:"access_password,omitempty"`
|
||||||
|
Provider string `json:"provider"`
|
||||||
|
Bucket string `json:"bucket"`
|
||||||
|
}
|
||||||
|
DownloadAlbumRequest {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Provider string `json:"provider"`
|
||||||
|
Bucket string `json:"bucket"`
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// 文件上传
|
// 文件上传
|
||||||
@@ -691,7 +708,7 @@ service auth {
|
|||||||
|
|
||||||
// 获取最近上传图片列表
|
// 获取最近上传图片列表
|
||||||
@handler queryRecentImageList
|
@handler queryRecentImageList
|
||||||
post /image/recent/list returns (RecentListResponse)
|
post /image/recent/list (RecentListRequest) returns (RecentListResponse)
|
||||||
|
|
||||||
// 获取地点相册列表
|
// 获取地点相册列表
|
||||||
@handler queryLocationImageList
|
@handler queryLocationImageList
|
||||||
@@ -728,6 +745,14 @@ service auth {
|
|||||||
// 获取存储桶的容量信息
|
// 获取存储桶的容量信息
|
||||||
@handler getBucketCapacity
|
@handler getBucketCapacity
|
||||||
post /bucket/capacity (BucketCapacityRequest) returns (BucketCapacityResponse)
|
post /bucket/capacity (BucketCapacityRequest) returns (BucketCapacityResponse)
|
||||||
|
|
||||||
|
// 分享相册
|
||||||
|
@handler shareAlbum
|
||||||
|
post /album/share (ShareAlbumRequest) returns (string)
|
||||||
|
|
||||||
|
// 下载相册
|
||||||
|
@handler downloadAlbum
|
||||||
|
post /album/download (DownloadAlbumRequest) returns (string)
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
package upscale
|
package phone
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/zeromicro/go-zero/rest/httpx"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"schisandra-album-cloud-microservices/app/auth/api/internal/logic/upscale"
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"schisandra-album-cloud-microservices/app/auth/api/internal/logic/phone"
|
||||||
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
|
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
|
||||||
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
|
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
|
||||||
|
|
||||||
"schisandra-album-cloud-microservices/common/xhttp"
|
"schisandra-album-cloud-microservices/common/xhttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ func UploadImageHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
l := upscale.NewUploadImageLogic(r.Context(), svcCtx)
|
l := phone.NewUploadImageLogic(r.Context(), svcCtx)
|
||||||
err := l.UploadImage(r, &req)
|
err := l.UploadImage(r, &req)
|
||||||
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
|
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
|
||||||
}
|
}
|
@@ -11,11 +11,11 @@ import (
|
|||||||
client "schisandra-album-cloud-microservices/app/auth/api/internal/handler/client"
|
client "schisandra-album-cloud-microservices/app/auth/api/internal/handler/client"
|
||||||
comment "schisandra-album-cloud-microservices/app/auth/api/internal/handler/comment"
|
comment "schisandra-album-cloud-microservices/app/auth/api/internal/handler/comment"
|
||||||
oauth "schisandra-album-cloud-microservices/app/auth/api/internal/handler/oauth"
|
oauth "schisandra-album-cloud-microservices/app/auth/api/internal/handler/oauth"
|
||||||
|
phone "schisandra-album-cloud-microservices/app/auth/api/internal/handler/phone"
|
||||||
share "schisandra-album-cloud-microservices/app/auth/api/internal/handler/share"
|
share "schisandra-album-cloud-microservices/app/auth/api/internal/handler/share"
|
||||||
sms "schisandra-album-cloud-microservices/app/auth/api/internal/handler/sms"
|
sms "schisandra-album-cloud-microservices/app/auth/api/internal/handler/sms"
|
||||||
storage "schisandra-album-cloud-microservices/app/auth/api/internal/handler/storage"
|
storage "schisandra-album-cloud-microservices/app/auth/api/internal/handler/storage"
|
||||||
token "schisandra-album-cloud-microservices/app/auth/api/internal/handler/token"
|
token "schisandra-album-cloud-microservices/app/auth/api/internal/handler/token"
|
||||||
upscale "schisandra-album-cloud-microservices/app/auth/api/internal/handler/upscale"
|
|
||||||
user "schisandra-album-cloud-microservices/app/auth/api/internal/handler/user"
|
user "schisandra-album-cloud-microservices/app/auth/api/internal/handler/user"
|
||||||
websocket "schisandra-album-cloud-microservices/app/auth/api/internal/handler/websocket"
|
websocket "schisandra-album-cloud-microservices/app/auth/api/internal/handler/websocket"
|
||||||
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
|
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
|
||||||
@@ -159,6 +159,22 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
rest.WithMaxBytes(1048576),
|
rest.WithMaxBytes(1048576),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
rest.WithMiddlewares(
|
||||||
|
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.NonceMiddleware},
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/upload",
|
||||||
|
Handler: phone.UploadImageHandler(serverCtx),
|
||||||
|
},
|
||||||
|
}...,
|
||||||
|
),
|
||||||
|
rest.WithPrefix("/api/auth/phone"),
|
||||||
|
rest.WithTimeout(10000*time.Millisecond),
|
||||||
|
rest.WithMaxBytes(10485760),
|
||||||
|
)
|
||||||
|
|
||||||
server.AddRoutes(
|
server.AddRoutes(
|
||||||
rest.WithMiddlewares(
|
rest.WithMiddlewares(
|
||||||
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware, serverCtx.NonceMiddleware},
|
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware, serverCtx.NonceMiddleware},
|
||||||
@@ -241,6 +257,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
Path: "/album/detail/list",
|
Path: "/album/detail/list",
|
||||||
Handler: storage.GetAlbumDetailHandler(serverCtx),
|
Handler: storage.GetAlbumDetailHandler(serverCtx),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/album/download",
|
||||||
|
Handler: storage.DownloadAlbumHandler(serverCtx),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
Path: "/album/list",
|
Path: "/album/list",
|
||||||
@@ -251,6 +272,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
Path: "/album/rename",
|
Path: "/album/rename",
|
||||||
Handler: storage.RenameAlbumHandler(serverCtx),
|
Handler: storage.RenameAlbumHandler(serverCtx),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/album/share",
|
||||||
|
Handler: storage.ShareAlbumHandler(serverCtx),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
Path: "/bucket/capacity",
|
Path: "/bucket/capacity",
|
||||||
@@ -361,22 +387,6 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
rest.WithMaxBytes(1048576),
|
rest.WithMaxBytes(1048576),
|
||||||
)
|
)
|
||||||
|
|
||||||
server.AddRoutes(
|
|
||||||
rest.WithMiddlewares(
|
|
||||||
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.NonceMiddleware},
|
|
||||||
[]rest.Route{
|
|
||||||
{
|
|
||||||
Method: http.MethodPost,
|
|
||||||
Path: "/phone/upload",
|
|
||||||
Handler: upscale.UploadImageHandler(serverCtx),
|
|
||||||
},
|
|
||||||
}...,
|
|
||||||
),
|
|
||||||
rest.WithPrefix("/api/auth/upscale"),
|
|
||||||
rest.WithTimeout(10000*time.Millisecond),
|
|
||||||
rest.WithMaxBytes(10485760),
|
|
||||||
)
|
|
||||||
|
|
||||||
server.AddRoutes(
|
server.AddRoutes(
|
||||||
rest.WithMiddlewares(
|
rest.WithMiddlewares(
|
||||||
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.NonceMiddleware},
|
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.NonceMiddleware},
|
||||||
|
@@ -0,0 +1,29 @@
|
|||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"schisandra-album-cloud-microservices/app/auth/api/internal/logic/storage"
|
||||||
|
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
|
||||||
|
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
|
||||||
|
"schisandra-album-cloud-microservices/common/xhttp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DownloadAlbumHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.DownloadAlbumRequest
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := storage.NewDownloadAlbumLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.DownloadAlbum(&req)
|
||||||
|
if err != nil {
|
||||||
|
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -3,15 +3,23 @@ package storage
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
"schisandra-album-cloud-microservices/app/auth/api/internal/logic/storage"
|
"schisandra-album-cloud-microservices/app/auth/api/internal/logic/storage"
|
||||||
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
|
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
|
||||||
|
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
|
||||||
"schisandra-album-cloud-microservices/common/xhttp"
|
"schisandra-album-cloud-microservices/common/xhttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func QueryRecentImageListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
func QueryRecentImageListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.RecentListRequest
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
l := storage.NewQueryRecentImageListLogic(r.Context(), svcCtx)
|
l := storage.NewQueryRecentImageListLogic(r.Context(), svcCtx)
|
||||||
resp, err := l.QueryRecentImageList()
|
resp, err := l.QueryRecentImageList(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
|
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
|
||||||
} else {
|
} else {
|
||||||
|
29
app/auth/api/internal/handler/storage/share_album_handler.go
Normal file
29
app/auth/api/internal/handler/storage/share_album_handler.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"schisandra-album-cloud-microservices/app/auth/api/internal/logic/storage"
|
||||||
|
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
|
||||||
|
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
|
||||||
|
"schisandra-album-cloud-microservices/common/xhttp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ShareAlbumHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.ShareAlbumRequest
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := storage.NewShareAlbumLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.ShareAlbum(&req)
|
||||||
|
if err != nil {
|
||||||
|
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,17 +1,16 @@
|
|||||||
package upscale
|
package phone
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"schisandra-album-cloud-microservices/app/auth/api/internal/logic/websocket"
|
"schisandra-album-cloud-microservices/app/auth/api/internal/logic/websocket"
|
||||||
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
|
|
||||||
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
|
|
||||||
|
|
||||||
"schisandra-album-cloud-microservices/common/xhttp"
|
|
||||||
|
|
||||||
"schisandra-album-cloud-microservices/common/errors"
|
"schisandra-album-cloud-microservices/common/errors"
|
||||||
"schisandra-album-cloud-microservices/common/jwt"
|
"schisandra-album-cloud-microservices/common/jwt"
|
||||||
|
"schisandra-album-cloud-microservices/common/xhttp"
|
||||||
|
|
||||||
|
"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"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
)
|
)
|
||||||
@@ -30,7 +29,7 @@ func NewUploadImageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Uploa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *UploadImageLogic) UploadImage(r *http.Request, req *types.UploadRequest) (err error) {
|
func (l *UploadImageLogic) UploadImage(r *http.Request, req *types.UploadRequest) error {
|
||||||
token, ok := jwt.ParseAccessToken(l.svcCtx.Config.Auth.AccessSecret, req.AccessToken)
|
token, ok := jwt.ParseAccessToken(l.svcCtx.Config.Auth.AccessSecret, req.AccessToken)
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New(http.StatusForbidden, "invalid access token")
|
return errors.New(http.StatusForbidden, "invalid access token")
|
@@ -140,6 +140,18 @@ func (l *QueryShareImageLogic) queryShareImageFromSource(storageShare *model.Sca
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加载用户oss配置信息
|
||||||
|
cacheOssConfigKey := constant.UserOssConfigPrefix + storageShare.UserID + ":" + storageShare.Provider
|
||||||
|
ossConfig, err := l.getOssConfigFromCacheOrDb(cacheOssConfigKey, storageShare.UserID, storageShare.Provider)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
service, err := l.svcCtx.StorageManager.GetStorage(storageShare.UserID, ossConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("get storage failed")
|
||||||
|
}
|
||||||
|
|
||||||
// 使用 errgroup 和 semaphore 并发处理图片信息
|
// 使用 errgroup 和 semaphore 并发处理图片信息
|
||||||
var ResultList []types.ShareImageListMeta
|
var ResultList []types.ShareImageListMeta
|
||||||
g, ctx := errgroup.WithContext(l.ctx)
|
g, ctx := errgroup.WithContext(l.ctx)
|
||||||
@@ -152,17 +164,6 @@ func (l *QueryShareImageLogic) queryShareImageFromSource(storageShare *model.Sca
|
|||||||
}
|
}
|
||||||
g.Go(func() error {
|
g.Go(func() error {
|
||||||
defer sem.Release(1)
|
defer sem.Release(1)
|
||||||
// 加载用户oss配置信息
|
|
||||||
cacheOssConfigKey := constant.UserOssConfigPrefix + storageShare.UserID + ":" + imgInfo.Provider
|
|
||||||
ossConfig, err := l.getOssConfigFromCacheOrDb(cacheOssConfigKey, storageShare.UserID, imgInfo.Provider)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
service, err := l.svcCtx.StorageManager.GetStorage(storageShare.UserID, ossConfig)
|
|
||||||
if err != nil {
|
|
||||||
return errors.New("get storage failed")
|
|
||||||
}
|
|
||||||
ossURL, err := service.PresignedURL(ctx, ossConfig.BucketName, imgInfo.Path, 30*time.Minute)
|
ossURL, err := service.PresignedURL(ctx, ossConfig.BucketName, imgInfo.Path, 30*time.Minute)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("get presigned url failed")
|
return errors.New("get presigned url failed")
|
||||||
|
@@ -101,6 +101,8 @@ func (l *UploadShareImageLogic) UploadShareImage(req *types.ShareImageRequest) (
|
|||||||
ValidityPeriod: int64(duration),
|
ValidityPeriod: int64(duration),
|
||||||
ExpireTime: expiryTime,
|
ExpireTime: expiryTime,
|
||||||
ImageCount: int64(len(req.Images)),
|
ImageCount: int64(len(req.Images)),
|
||||||
|
Provider: req.Provider,
|
||||||
|
Bucket: req.Bucket,
|
||||||
}
|
}
|
||||||
err = tx.ScaStorageShare.Create(&storageShare)
|
err = tx.ScaStorageShare.Create(&storageShare)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -29,16 +29,31 @@ func (l *DeleteAlbumLogic) DeleteAlbum(req *types.AlbumDeleteRequest) (resp stri
|
|||||||
if !ok {
|
if !ok {
|
||||||
return "", errors.New("user_id not found")
|
return "", errors.New("user_id not found")
|
||||||
}
|
}
|
||||||
info, err := l.svcCtx.DB.ScaStorageAlbum.Where(l.svcCtx.DB.ScaStorageAlbum.ID.Eq(req.ID), l.svcCtx.DB.ScaStorageAlbum.UserID.Eq(uid)).Delete()
|
tx := l.svcCtx.DB.Begin()
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
info, err := tx.ScaStorageAlbum.Where(tx.ScaStorageAlbum.ID.Eq(req.ID), tx.ScaStorageAlbum.UserID.Eq(uid)).Delete()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if info.RowsAffected == 0 {
|
if info.RowsAffected == 0 {
|
||||||
|
tx.Rollback()
|
||||||
return "", errors.New("album not found")
|
return "", errors.New("album not found")
|
||||||
}
|
}
|
||||||
storageInfo := l.svcCtx.DB.ScaStorageInfo
|
storageInfo := tx.ScaStorageInfo
|
||||||
_, err = storageInfo.Where(storageInfo.AlbumID.Eq(req.ID), storageInfo.UserID.Eq(uid)).Update(storageInfo.AlbumID, 0)
|
_, err = storageInfo.Where(storageInfo.AlbumID.Eq(req.ID), storageInfo.UserID.Eq(uid)).Delete()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return "success", nil
|
return "success", nil
|
||||||
|
30
app/auth/api/internal/logic/storage/download_album_logic.go
Normal file
30
app/auth/api/internal/logic/storage/download_album_logic.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"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 DownloadAlbumLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDownloadAlbumLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DownloadAlbumLogic {
|
||||||
|
return &DownloadAlbumLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *DownloadAlbumLogic) DownloadAlbum(req *types.DownloadAlbumRequest) (resp string, err error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
@@ -7,6 +7,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
"golang.org/x/sync/semaphore"
|
||||||
"gorm.io/gen"
|
"gorm.io/gen"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -59,8 +61,11 @@ func (l *QueryAllImageListLogic) QueryAllImageList(req *types.AllImageListReques
|
|||||||
if err := json.Unmarshal([]byte(cachedResult), &cachedResponse); err == nil {
|
if err := json.Unmarshal([]byte(cachedResult), &cachedResponse); err == nil {
|
||||||
return &cachedResponse, nil
|
return &cachedResponse, nil
|
||||||
}
|
}
|
||||||
logx.Error("Failed to unmarshal cached image list:", err)
|
logx.Error("Failed to unmarshal cached image list, deleting invalid cache:", err)
|
||||||
return nil, errors.New("get cached image list failed")
|
// 删除无效缓存
|
||||||
|
if err := l.svcCtx.RedisClient.Del(l.ctx, cacheKey).Err(); err != nil {
|
||||||
|
logx.Error("Failed to delete invalid cache:", err)
|
||||||
|
}
|
||||||
} else if !errors.Is(err, redis.Nil) {
|
} else if !errors.Is(err, redis.Nil) {
|
||||||
logx.Error("Redis error:", err)
|
logx.Error("Redis error:", err)
|
||||||
return nil, errors.New("get cached image list failed")
|
return nil, errors.New("get cached image list failed")
|
||||||
@@ -115,25 +120,30 @@ func (l *QueryAllImageListLogic) QueryAllImageList(req *types.AllImageListReques
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 按日期进行分组
|
// 按日期进行分组
|
||||||
var wg sync.WaitGroup
|
g, ctx := errgroup.WithContext(l.ctx)
|
||||||
|
sem := semaphore.NewWeighted(10) // 限制并发数为 10
|
||||||
groupedImages := sync.Map{}
|
groupedImages := sync.Map{}
|
||||||
|
|
||||||
for _, dbFileInfo := range storageInfoList {
|
for _, dbFileInfo := range storageInfoList {
|
||||||
wg.Add(1)
|
dbFileInfo := dbFileInfo // 创建局部变量以避免闭包问题
|
||||||
go func(dbFileInfo *types.FileInfoResult) {
|
if err := sem.Acquire(ctx, 1); err != nil {
|
||||||
defer wg.Done()
|
logx.Error("Failed to acquire semaphore:", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
g.Go(func() error {
|
||||||
|
defer sem.Release(1)
|
||||||
weekday := WeekdayMap[dbFileInfo.CreatedAt.Weekday()]
|
weekday := WeekdayMap[dbFileInfo.CreatedAt.Weekday()]
|
||||||
date := dbFileInfo.CreatedAt.Format("2006年1月2日 星期" + weekday)
|
date := dbFileInfo.CreatedAt.Format("2006年1月2日 星期" + weekday)
|
||||||
reqParams := make(url.Values)
|
reqParams := make(url.Values)
|
||||||
presignedUrl, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, dbFileInfo.ThumbPath, time.Hour*24*7, reqParams)
|
presignedUrl, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, dbFileInfo.ThumbPath, time.Hour*24*7, reqParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logx.Error(err)
|
logx.Error(err)
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Hour*24*7)
|
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Hour*24*7)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logx.Error(err)
|
logx.Error(err)
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
// 使用 Load 或 Store 确保原子操作
|
// 使用 Load 或 Store 确保原子操作
|
||||||
value, _ := groupedImages.LoadOrStore(date, []types.ImageMeta{})
|
value, _ := groupedImages.LoadOrStore(date, []types.ImageMeta{})
|
||||||
@@ -151,9 +161,13 @@ func (l *QueryAllImageListLogic) QueryAllImageList(req *types.AllImageListReques
|
|||||||
|
|
||||||
// 重新存储更新后的图像列表
|
// 重新存储更新后的图像列表
|
||||||
groupedImages.Store(date, images)
|
groupedImages.Store(date, images)
|
||||||
}(&dbFileInfo)
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 等待所有 goroutine 完成
|
||||||
|
if err = g.Wait(); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
wg.Wait()
|
|
||||||
var imageList []types.AllImageDetail
|
var imageList []types.AllImageDetail
|
||||||
groupedImages.Range(func(key, value interface{}) bool {
|
groupedImages.Range(func(key, value interface{}) bool {
|
||||||
imageList = append(imageList, types.AllImageDetail{
|
imageList = append(imageList, types.AllImageDetail{
|
||||||
@@ -162,11 +176,13 @@ func (l *QueryAllImageListLogic) QueryAllImageList(req *types.AllImageListReques
|
|||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
// 按日期排序,最新的在最上面
|
|
||||||
sort.Slice(imageList, func(i, j int) bool {
|
sort.Slice(imageList, func(i, j int) bool {
|
||||||
dateI, _ := time.Parse("2006年1月2日 星期一", imageList[i].Date)
|
if len(imageList[i].List) == 0 || len(imageList[j].List) == 0 {
|
||||||
dateJ, _ := time.Parse("2006年1月2日 星期一", imageList[j].Date)
|
return false // 空列表不参与排序
|
||||||
return dateI.After(dateJ)
|
}
|
||||||
|
createdAtI, _ := time.Parse("2006-01-02 15:04:05", imageList[i].List[0].CreatedAt)
|
||||||
|
createdAtJ, _ := time.Parse("2006-01-02 15:04:05", imageList[j].List[0].CreatedAt)
|
||||||
|
return createdAtI.After(createdAtJ) // 降序排序
|
||||||
})
|
})
|
||||||
resp = &types.AllImageListResponse{
|
resp = &types.AllImageListResponse{
|
||||||
Records: imageList,
|
Records: imageList,
|
||||||
|
@@ -4,7 +4,17 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
"golang.org/x/sync/semaphore"
|
||||||
|
"math/rand"
|
||||||
|
"net/url"
|
||||||
|
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
|
||||||
"schisandra-album-cloud-microservices/common/constant"
|
"schisandra-album-cloud-microservices/common/constant"
|
||||||
|
"schisandra-album-cloud-microservices/common/encrypt"
|
||||||
|
storageConfig "schisandra-album-cloud-microservices/common/storage/config"
|
||||||
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -28,72 +38,121 @@ func NewQueryRecentImageListLogic(ctx context.Context, svcCtx *svc.ServiceContex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *QueryRecentImageListLogic) QueryRecentImageList() (resp *types.RecentListResponse, err error) {
|
func (l *QueryRecentImageListLogic) QueryRecentImageList(req *types.RecentListRequest) (resp *types.RecentListResponse, err error) {
|
||||||
uid, ok := l.ctx.Value("user_id").(string)
|
uid, ok := l.ctx.Value("user_id").(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("user_id not found")
|
return nil, errors.New("user_id not found")
|
||||||
}
|
}
|
||||||
|
// 缓存获取数据 v1.0.0
|
||||||
redisKeyPattern := constant.ImageRecentPrefix + uid + ":*"
|
cacheKey := fmt.Sprintf("%s%s:%s:%s:%s", constant.ImageCachePrefix, uid, "recent", req.Provider, req.Bucket)
|
||||||
iter := l.svcCtx.RedisClient.Scan(l.ctx, 0, redisKeyPattern, 0).Iterator()
|
// 尝试从缓存获取
|
||||||
var keys []string
|
cachedResult, err := l.svcCtx.RedisClient.Get(l.ctx, cacheKey).Result()
|
||||||
for iter.Next(l.ctx) {
|
if err == nil {
|
||||||
keys = append(keys, iter.Val())
|
var cachedResponse types.RecentListResponse
|
||||||
|
if err := json.Unmarshal([]byte(cachedResult), &cachedResponse); err == nil {
|
||||||
|
return &cachedResponse, nil
|
||||||
|
}
|
||||||
|
logx.Error("Failed to unmarshal cached image list, deleting invalid cache:", err)
|
||||||
|
// 删除无效缓存
|
||||||
|
if err := l.svcCtx.RedisClient.Del(l.ctx, cacheKey).Err(); err != nil {
|
||||||
|
logx.Error("Failed to delete invalid cache:", err)
|
||||||
|
}
|
||||||
|
} else if !errors.Is(err, redis.Nil) {
|
||||||
|
logx.Error("Redis error:", err)
|
||||||
|
return nil, errors.New("get cached image list failed")
|
||||||
}
|
}
|
||||||
if err := iter.Err(); err != nil {
|
// 缓存未命中,从数据库中查询
|
||||||
logx.Error(err)
|
storageInfo := l.svcCtx.DB.ScaStorageInfo
|
||||||
return nil, errors.New("scan recent file list failed")
|
storageThumb := l.svcCtx.DB.ScaStorageThumb
|
||||||
}
|
// 获取当前时间
|
||||||
|
now := time.Now()
|
||||||
if len(keys) == 0 {
|
// 计算30天前的时间
|
||||||
return &types.RecentListResponse{Records: []types.AllImageDetail{}}, nil
|
thirtyDaysAgo := now.AddDate(0, 0, -30)
|
||||||
}
|
var storageInfoList []types.FileInfoResult
|
||||||
|
err = storageInfo.Select(
|
||||||
cmds, err := l.svcCtx.RedisClient.MGet(l.ctx, keys...).Result()
|
storageInfo.ID,
|
||||||
|
storageInfo.FileName,
|
||||||
|
storageInfo.CreatedAt,
|
||||||
|
storageThumb.ThumbPath,
|
||||||
|
storageInfo.Path,
|
||||||
|
storageThumb.ThumbW,
|
||||||
|
storageThumb.ThumbH,
|
||||||
|
storageThumb.ThumbSize).
|
||||||
|
LeftJoin(storageThumb, storageInfo.ID.EqCol(storageThumb.InfoID)).
|
||||||
|
Where(storageInfo.UserID.Eq(uid),
|
||||||
|
storageInfo.Provider.Eq(req.Provider),
|
||||||
|
storageInfo.Bucket.Eq(req.Bucket),
|
||||||
|
storageInfo.Type.Neq(constant.ImageTypeShared),
|
||||||
|
storageInfo.CreatedAt.Gt(thirtyDaysAgo)).
|
||||||
|
Order(storageInfo.CreatedAt.Desc()).Scan(&storageInfoList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logx.Error(err)
|
return nil, err
|
||||||
return nil, errors.New("get recent file list failed")
|
}
|
||||||
|
if len(storageInfoList) == 0 {
|
||||||
|
return &types.RecentListResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
// 加载用户oss配置信息
|
||||||
|
cacheOssConfigKey := constant.UserOssConfigPrefix + uid + ":" + req.Provider
|
||||||
|
ossConfig, err := l.getOssConfigFromCacheOrDb(cacheOssConfigKey, uid, req.Provider)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
service, err := l.svcCtx.StorageManager.GetStorage(uid, ossConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("get storage failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按日期进行分组
|
||||||
|
g, ctx := errgroup.WithContext(l.ctx)
|
||||||
|
sem := semaphore.NewWeighted(10) // 限制并发数为 10
|
||||||
groupedImages := sync.Map{}
|
groupedImages := sync.Map{}
|
||||||
|
|
||||||
for _, cmd := range cmds {
|
for _, dbFileInfo := range storageInfoList {
|
||||||
if cmd == nil {
|
dbFileInfo := dbFileInfo // 创建局部变量以避免闭包问题
|
||||||
|
if err := sem.Acquire(ctx, 1); err != nil {
|
||||||
|
logx.Error("Failed to acquire semaphore:", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val, ok := cmd.(string)
|
g.Go(func() error {
|
||||||
if !ok {
|
defer sem.Release(1)
|
||||||
logx.Error("invalid value type")
|
weekday := WeekdayMap[dbFileInfo.CreatedAt.Weekday()]
|
||||||
return nil, errors.New("invalid value type")
|
date := dbFileInfo.CreatedAt.Format("2006年1月2日 星期" + weekday)
|
||||||
}
|
reqParams := make(url.Values)
|
||||||
var imageMeta types.ImageMeta
|
presignedUrl, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, dbFileInfo.ThumbPath, time.Hour*24*7, reqParams)
|
||||||
err = json.Unmarshal([]byte(val), &imageMeta)
|
if err != nil {
|
||||||
if err != nil {
|
logx.Error(err)
|
||||||
logx.Error(err)
|
return err
|
||||||
return nil, errors.New("unmarshal recent file list failed")
|
|
||||||
}
|
|
||||||
parse, err := time.Parse("2006-01-02 15:04:05", imageMeta.CreatedAt)
|
|
||||||
if err != nil {
|
|
||||||
logx.Error(err)
|
|
||||||
return nil, errors.New("parse recent file list failed")
|
|
||||||
}
|
|
||||||
date := parse.Format("2006年1月2日 星期" + WeekdayMap[parse.Weekday()])
|
|
||||||
// 使用LoadOrStore来检查并存储或者追加
|
|
||||||
wg.Add(1)
|
|
||||||
go func(date string, imageMeta types.ImageMeta) {
|
|
||||||
defer wg.Done()
|
|
||||||
value, loaded := groupedImages.LoadOrStore(date, []types.ImageMeta{imageMeta})
|
|
||||||
if loaded {
|
|
||||||
images := value.([]types.ImageMeta)
|
|
||||||
images = append(images, imageMeta)
|
|
||||||
groupedImages.Store(date, images)
|
|
||||||
}
|
}
|
||||||
}(date, imageMeta)
|
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Hour*24*7)
|
||||||
|
if err != nil {
|
||||||
|
logx.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// 使用 Load 或 Store 确保原子操作
|
||||||
|
value, _ := groupedImages.LoadOrStore(date, []types.ImageMeta{})
|
||||||
|
images := value.([]types.ImageMeta)
|
||||||
|
|
||||||
|
images = append(images, types.ImageMeta{
|
||||||
|
ID: dbFileInfo.ID,
|
||||||
|
FileName: dbFileInfo.FileName,
|
||||||
|
Thumbnail: presignedUrl.String(),
|
||||||
|
URL: url,
|
||||||
|
Width: dbFileInfo.ThumbW,
|
||||||
|
Height: dbFileInfo.ThumbH,
|
||||||
|
CreatedAt: dbFileInfo.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||||
|
})
|
||||||
|
|
||||||
|
// 重新存储更新后的图像列表
|
||||||
|
groupedImages.Store(date, images)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 等待所有 goroutine 完成
|
||||||
|
if err = g.Wait(); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
var imageList []types.AllImageDetail
|
var imageList []types.AllImageDetail
|
||||||
groupedImages.Range(func(key, value interface{}) bool {
|
groupedImages.Range(func(key, value interface{}) bool {
|
||||||
imageList = append(imageList, types.AllImageDetail{
|
imageList = append(imageList, types.AllImageDetail{
|
||||||
@@ -102,7 +161,87 @@ func (l *QueryRecentImageListLogic) QueryRecentImageList() (resp *types.RecentLi
|
|||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return &types.RecentListResponse{
|
sort.Slice(imageList, func(i, j int) bool {
|
||||||
|
if len(imageList[i].List) == 0 || len(imageList[j].List) == 0 {
|
||||||
|
return false // 空列表不参与排序
|
||||||
|
}
|
||||||
|
createdAtI, _ := time.Parse("2006-01-02 15:04:05", imageList[i].List[0].CreatedAt)
|
||||||
|
createdAtJ, _ := time.Parse("2006-01-02 15:04:05", imageList[j].List[0].CreatedAt)
|
||||||
|
return createdAtI.After(createdAtJ) // 降序排序
|
||||||
|
})
|
||||||
|
resp = &types.RecentListResponse{
|
||||||
Records: imageList,
|
Records: imageList,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缓存结果
|
||||||
|
if data, err := json.Marshal(resp); err == nil {
|
||||||
|
expireTime := 5*time.Minute + time.Duration(rand.Intn(300))*time.Second
|
||||||
|
if err := l.svcCtx.RedisClient.Set(l.ctx, cacheKey, data, expireTime).Err(); err != nil {
|
||||||
|
logx.Error("Failed to cache image list:", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logx.Error("Failed to marshal image list for caching:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取解密操作为函数
|
||||||
|
func (l *QueryRecentImageListLogic) decryptConfig(config *model.ScaStorageConfig) (*storageConfig.StorageConfig, error) {
|
||||||
|
accessKey, err := encrypt.Decrypt(config.AccessKey, l.svcCtx.Config.Encrypt.Key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("decrypt access key failed")
|
||||||
|
}
|
||||||
|
secretKey, err := encrypt.Decrypt(config.SecretKey, l.svcCtx.Config.Encrypt.Key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("decrypt secret key failed")
|
||||||
|
}
|
||||||
|
return &storageConfig.StorageConfig{
|
||||||
|
Provider: config.Provider,
|
||||||
|
Endpoint: config.Endpoint,
|
||||||
|
AccessKey: accessKey,
|
||||||
|
SecretKey: secretKey,
|
||||||
|
BucketName: config.Bucket,
|
||||||
|
Region: config.Region,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从缓存或数据库中获取 OSS 配置
|
||||||
|
func (l *QueryRecentImageListLogic) getOssConfigFromCacheOrDb(cacheKey, uid, provider string) (*storageConfig.StorageConfig, error) {
|
||||||
|
result, err := l.svcCtx.RedisClient.Get(l.ctx, cacheKey).Result()
|
||||||
|
if err != nil && !errors.Is(err, redis.Nil) {
|
||||||
|
return nil, errors.New("get oss config failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
var ossConfig *storageConfig.StorageConfig
|
||||||
|
if result != "" {
|
||||||
|
var redisOssConfig model.ScaStorageConfig
|
||||||
|
if err = json.Unmarshal([]byte(result), &redisOssConfig); err != nil {
|
||||||
|
return nil, errors.New("unmarshal oss config failed")
|
||||||
|
}
|
||||||
|
return l.decryptConfig(&redisOssConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缓存未命中,从数据库中加载
|
||||||
|
scaOssConfig := l.svcCtx.DB.ScaStorageConfig
|
||||||
|
dbOssConfig, err := scaOssConfig.Where(scaOssConfig.UserID.Eq(uid), scaOssConfig.Provider.Eq(provider)).First()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缓存数据库配置
|
||||||
|
ossConfig, err = l.decryptConfig(dbOssConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
marshalData, err := json.Marshal(dbOssConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("marshal oss config failed")
|
||||||
|
}
|
||||||
|
err = l.svcCtx.RedisClient.Set(l.ctx, cacheKey, marshalData, 0).Err()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("set oss config failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return ossConfig, nil
|
||||||
|
}
|
||||||
|
126
app/auth/api/internal/logic/storage/share_album_logic.go
Normal file
126
app/auth/api/internal/logic/storage/share_album_logic.go
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"github.com/ccpwcn/kgo"
|
||||||
|
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
|
||||||
|
"schisandra-album-cloud-microservices/common/constant"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"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 ShareAlbumLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewShareAlbumLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ShareAlbumLogic {
|
||||||
|
return &ShareAlbumLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ShareAlbumLogic) ShareAlbum(req *types.ShareAlbumRequest) (resp string, err error) {
|
||||||
|
uid, ok := l.ctx.Value("user_id").(string)
|
||||||
|
if !ok {
|
||||||
|
return "", errors.New("user_id not found")
|
||||||
|
}
|
||||||
|
tx := l.svcCtx.DB.Begin()
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
storageAlbum := tx.ScaStorageAlbum
|
||||||
|
info, err := storageAlbum.Where(storageAlbum.ID.Eq(req.ID), storageAlbum.UserID.Eq(uid)).
|
||||||
|
Update(storageAlbum.AlbumType, constant.AlbumTypeShared)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if info.RowsAffected == 0 {
|
||||||
|
tx.Rollback()
|
||||||
|
return "", errors.New("album not found")
|
||||||
|
}
|
||||||
|
// 更新图片信息
|
||||||
|
storageInfo := tx.ScaStorageInfo
|
||||||
|
_, err = storageInfo.Where(storageInfo.AlbumID.Eq(req.ID), storageInfo.UserID.Eq(uid)).
|
||||||
|
Update(storageInfo.Type, constant.ImageTypeShared)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// 查询图片数量
|
||||||
|
var imageCount int64
|
||||||
|
err = storageInfo.Select(
|
||||||
|
storageInfo.ID.Count().As("image_count")).
|
||||||
|
Where(storageInfo.AlbumID.Eq(req.ID), storageInfo.UserID.Eq(uid)).
|
||||||
|
Group(storageInfo.AlbumID).Scan(&imageCount)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
duration, err := strconv.Atoi(req.ExpireDate)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.New("invalid expire date")
|
||||||
|
}
|
||||||
|
expiryTime := l.GenerateExpiryTime(time.Now(), duration)
|
||||||
|
storageShare := tx.ScaStorageShare
|
||||||
|
storageShareInfo := &model.ScaStorageShare{
|
||||||
|
UserID: uid,
|
||||||
|
AlbumID: req.ID,
|
||||||
|
InviteCode: kgo.SimpleUuid(),
|
||||||
|
ValidityPeriod: int64(duration),
|
||||||
|
ExpireTime: expiryTime,
|
||||||
|
AccessPassword: req.AccessPassword,
|
||||||
|
VisitLimit: req.AccessLimit,
|
||||||
|
ImageCount: imageCount,
|
||||||
|
Provider: req.Provider,
|
||||||
|
Bucket: req.Bucket,
|
||||||
|
Status: 0,
|
||||||
|
}
|
||||||
|
err = storageShare.Create(storageShareInfo)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
marshal, err := json.Marshal(storageShareInfo)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
cacheKey := constant.ImageSharePrefix + storageShareInfo.InviteCode
|
||||||
|
err = l.svcCtx.RedisClient.Set(l.ctx, cacheKey, marshal, time.Duration(duration)*time.Hour*24).Err()
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return "success", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateExpiryTime 函数接受当前时间和有效期(天为单位),返回过期时间
|
||||||
|
func (l *ShareAlbumLogic) GenerateExpiryTime(currentTime time.Time, durationInDays int) time.Time {
|
||||||
|
// 创建一个持续时间对象
|
||||||
|
duration := time.Duration(durationInDays) * 24 * time.Hour
|
||||||
|
// 将当前时间加上持续时间,得到过期时间
|
||||||
|
expiryTime := currentTime.Add(duration)
|
||||||
|
return expiryTime
|
||||||
|
}
|
@@ -15,7 +15,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"schisandra-album-cloud-microservices/app/aisvc/rpc/pb"
|
"schisandra-album-cloud-microservices/app/aisvc/rpc/pb"
|
||||||
@@ -83,7 +82,6 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
|
|||||||
faceId int64
|
faceId int64
|
||||||
filePath string
|
filePath string
|
||||||
minioFilePath string
|
minioFilePath string
|
||||||
presignedURL string
|
|
||||||
)
|
)
|
||||||
g, ctx := errgroup.WithContext(context.Background())
|
g, ctx := errgroup.WithContext(context.Background())
|
||||||
// 创建信号量,限制最大并发上传数(比如最多同时 5 个任务)
|
// 创建信号量,限制最大并发上传数(比如最多同时 5 个任务)
|
||||||
@@ -136,12 +134,11 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
|
|||||||
}
|
}
|
||||||
defer sem.Release(1)
|
defer sem.Release(1)
|
||||||
|
|
||||||
path, url, err := l.uploadFileToMinio(uid, header, thumbnail, result)
|
path, err := l.uploadFileToMinio(uid, header, thumbnail, result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
minioFilePath = path
|
minioFilePath = path
|
||||||
presignedURL = url
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -151,13 +148,12 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileUploadMessage := &types.FileUploadMessage{
|
fileUploadMessage := &types.FileUploadMessage{
|
||||||
UID: uid,
|
UID: uid,
|
||||||
Data: result,
|
Data: result,
|
||||||
FaceID: faceId,
|
FaceID: faceId,
|
||||||
FileHeader: header,
|
FileHeader: header,
|
||||||
FilePath: filePath,
|
FilePath: filePath,
|
||||||
PresignedURL: presignedURL,
|
ThumbPath: minioFilePath,
|
||||||
ThumbPath: minioFilePath,
|
|
||||||
}
|
}
|
||||||
// 转换为 JSON
|
// 转换为 JSON
|
||||||
messageData, err := json.Marshal(fileUploadMessage)
|
messageData, err := json.Marshal(fileUploadMessage)
|
||||||
@@ -241,7 +237,7 @@ func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHead
|
|||||||
return objectKey, nil
|
return objectKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *UploadFileLogic) uploadFileToMinio(uid string, header *multipart.FileHeader, file multipart.File, result types.File) (string, string, error) {
|
func (l *UploadFileLogic) uploadFileToMinio(uid string, header *multipart.FileHeader, file multipart.File, result types.File) (string, error) {
|
||||||
objectKey := path.Join(
|
objectKey := path.Join(
|
||||||
uid,
|
uid,
|
||||||
time.Now().Format("2006/01"), // 按年/月划分目录
|
time.Now().Format("2006/01"), // 按年/月划分目录
|
||||||
@@ -253,7 +249,7 @@ func (l *UploadFileLogic) uploadFileToMinio(uid string, header *multipart.FileHe
|
|||||||
err = l.svcCtx.MinioClient.MakeBucket(l.ctx, constant.ThumbnailBucketName, minio.MakeBucketOptions{Region: "us-east-1", ObjectLocking: true})
|
err = l.svcCtx.MinioClient.MakeBucket(l.ctx, constant.ThumbnailBucketName, minio.MakeBucketOptions{Region: "us-east-1", ObjectLocking: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logx.Errorf("Failed to create MinIO bucket: %v", err)
|
logx.Errorf("Failed to create MinIO bucket: %v", err)
|
||||||
return "", "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 上传到MinIO
|
// 上传到MinIO
|
||||||
@@ -268,14 +264,14 @@ func (l *UploadFileLogic) uploadFileToMinio(uid string, header *multipart.FileHe
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", err
|
||||||
}
|
}
|
||||||
reqParams := make(url.Values)
|
//reqParams := make(url.Values)
|
||||||
presignedURL, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, objectKey, time.Hour*24*7, reqParams)
|
//presignedURL, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, objectKey, time.Hour*24*7, reqParams)
|
||||||
if err != nil {
|
//if err != nil {
|
||||||
return "", "", err
|
// return "", "", err
|
||||||
}
|
//}
|
||||||
return objectKey, presignedURL.String(), nil
|
return objectKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提取解密操作为函数
|
// 提取解密操作为函数
|
||||||
|
@@ -19,7 +19,6 @@ import (
|
|||||||
"schisandra-album-cloud-microservices/common/nsqx"
|
"schisandra-album-cloud-microservices/common/nsqx"
|
||||||
"schisandra-album-cloud-microservices/common/storage/config"
|
"schisandra-album-cloud-microservices/common/storage/config"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type NsqImageProcessConsumer struct {
|
type NsqImageProcessConsumer struct {
|
||||||
@@ -61,7 +60,7 @@ func (c *NsqImageProcessConsumer) HandleMessage(msg *nsq.Message) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 将文件信息存入数据库
|
// 将文件信息存入数据库
|
||||||
storageId, err := c.saveFileInfoToDB(message.UID, message.Data.Bucket, message.Data.Provider, message.FileHeader, message.Data, message.FaceID, message.FilePath, locationId)
|
storageId, err := c.saveFileInfoToDB(message.UID, message.Data.Bucket, message.Data.Provider, message.FileHeader, message.Data, message.FaceID, message.FilePath, locationId, message.Data.AlbumId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -75,10 +74,10 @@ func (c *NsqImageProcessConsumer) HandleMessage(msg *nsq.Message) error {
|
|||||||
c.afterImageUpload(message.UID)
|
c.afterImageUpload(message.UID)
|
||||||
|
|
||||||
// redis 保存最近7天上传的文件列表
|
// redis 保存最近7天上传的文件列表
|
||||||
err = c.saveRecentFileList(message.UID, message.PresignedURL, storageId, message.Data, message.FileHeader.Filename)
|
//err = c.saveRecentFileList(message.UID, message.Thumbnail, message.URL, storageId, message.Data, message.FileHeader.Filename)
|
||||||
if err != nil {
|
//if err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
//}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -167,30 +166,31 @@ func (c *NsqImageProcessConsumer) classifyFile(mimeType string, isScreenshot boo
|
|||||||
return "unknown"
|
return "unknown"
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存最近7天上传的文件列表
|
//// 保存最近7天上传的文件列表
|
||||||
func (c *NsqImageProcessConsumer) saveRecentFileList(uid, url string, id int64, result types.File, filename string) error {
|
//func (c *NsqImageProcessConsumer) saveRecentFileList(uid, thumbnail, url string, id int64, result types.File, filename string) error {
|
||||||
|
//
|
||||||
redisKey := constant.ImageRecentPrefix + uid + ":" + strconv.FormatInt(id, 10)
|
// redisKey := constant.ImageRecentPrefix + uid + ":" + strconv.FormatInt(id, 10)
|
||||||
imageMeta := types.ImageMeta{
|
// imageMeta := types.ImageMeta{
|
||||||
ID: id,
|
// ID: id,
|
||||||
URL: url,
|
// URL: url,
|
||||||
FileName: filename,
|
// FileName: filename,
|
||||||
Width: result.Width,
|
// Width: result.ThumbW,
|
||||||
Height: result.Height,
|
// Height: result.ThumbH,
|
||||||
CreatedAt: time.Now().Format("2006-01-02 15:04:05"),
|
// Thumbnail: thumbnail,
|
||||||
}
|
// CreatedAt: time.Now().Format("2006-01-02 15:04:05"),
|
||||||
marshal, err := json.Marshal(imageMeta)
|
// }
|
||||||
if err != nil {
|
// marshal, err := json.Marshal(imageMeta)
|
||||||
logx.Error(err)
|
// if err != nil {
|
||||||
return errors.New("marshal image meta failed")
|
// logx.Error(err)
|
||||||
}
|
// return errors.New("marshal image meta failed")
|
||||||
err = c.svcCtx.RedisClient.Set(c.ctx, redisKey, marshal, time.Hour*24*7).Err()
|
// }
|
||||||
if err != nil {
|
// err = c.svcCtx.RedisClient.Set(c.ctx, redisKey, marshal, time.Hour*24*7).Err()
|
||||||
logx.Error(err)
|
// if err != nil {
|
||||||
return errors.New("save recent file list failed")
|
// logx.Error(err)
|
||||||
}
|
// return errors.New("save recent file list failed")
|
||||||
return nil
|
// }
|
||||||
}
|
// return nil
|
||||||
|
//}
|
||||||
|
|
||||||
// 提取解密操作为函数
|
// 提取解密操作为函数
|
||||||
func (c *NsqImageProcessConsumer) decryptConfig(dbConfig *model.ScaStorageConfig) (*config.StorageConfig, error) {
|
func (c *NsqImageProcessConsumer) decryptConfig(dbConfig *model.ScaStorageConfig) (*config.StorageConfig, error) {
|
||||||
@@ -259,7 +259,7 @@ func (c *NsqImageProcessConsumer) saveFileThumbnailInfoToDB(uid string, filePath
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 将 EXIF 和文件信息存入数据库
|
// 将 EXIF 和文件信息存入数据库
|
||||||
func (c *NsqImageProcessConsumer) saveFileInfoToDB(uid, bucket, provider string, header *multipart.FileHeader, result types.File, faceId int64, filePath string, locationID int64) (int64, error) {
|
func (c *NsqImageProcessConsumer) saveFileInfoToDB(uid, bucket, provider string, header *multipart.FileHeader, result types.File, faceId int64, filePath string, locationID, albumId int64) (int64, error) {
|
||||||
tx := c.svcCtx.DB.Begin()
|
tx := c.svcCtx.DB.Begin()
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@@ -281,6 +281,7 @@ func (c *NsqImageProcessConsumer) saveFileInfoToDB(uid, bucket, provider string,
|
|||||||
Width: result.Width,
|
Width: result.Width,
|
||||||
Height: result.Height,
|
Height: result.Height,
|
||||||
LocationID: locationID,
|
LocationID: locationID,
|
||||||
|
AlbumID: albumId,
|
||||||
}
|
}
|
||||||
err := tx.ScaStorageInfo.Create(scaStorageInfo)
|
err := tx.ScaStorageInfo.Create(scaStorageInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -22,17 +22,19 @@ type File struct {
|
|||||||
ThumbW float64 `json:"thumb_w"`
|
ThumbW float64 `json:"thumb_w"`
|
||||||
ThumbH float64 `json:"thumb_h"`
|
ThumbH float64 `json:"thumb_h"`
|
||||||
ThumbSize float64 `json:"thumb_size"`
|
ThumbSize float64 `json:"thumb_size"`
|
||||||
|
AlbumId int64 `json:"albumId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileUploadMessage represents a message sent to the user after a file upload.
|
// FileUploadMessage represents a message sent to the user after a file upload.
|
||||||
type FileUploadMessage struct {
|
type FileUploadMessage struct {
|
||||||
FaceID int64 `json:"face_id"`
|
FaceID int64 `json:"face_id"`
|
||||||
FileHeader *multipart.FileHeader `json:"fileHeader"`
|
FileHeader *multipart.FileHeader `json:"fileHeader"`
|
||||||
Data File `json:"data"`
|
Data File `json:"data"`
|
||||||
UID string `json:"uid"`
|
UID string `json:"uid"`
|
||||||
FilePath string `json:"filePath"`
|
FilePath string `json:"filePath"`
|
||||||
PresignedURL string `json:"presignedURL"`
|
URL string `json:"url"`
|
||||||
ThumbPath string `json:"thumbPath"`
|
ThumbPath string `json:"thumbPath"`
|
||||||
|
Thumbnail string `json:"thumbnail"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type FileInfoResult struct {
|
type FileInfoResult struct {
|
||||||
|
@@ -168,6 +168,12 @@ type DeleteRecordListResponse struct {
|
|||||||
Records []AllImageDetail `json:"records"`
|
Records []AllImageDetail `json:"records"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DownloadAlbumRequest struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Provider string `json:"provider"`
|
||||||
|
Bucket string `json:"bucket"`
|
||||||
|
}
|
||||||
|
|
||||||
type FaceDetailListRequest struct {
|
type FaceDetailListRequest struct {
|
||||||
FaceID int64 `json:"face_id"`
|
FaceID int64 `json:"face_id"`
|
||||||
Provider string `json:"provider"`
|
Provider string `json:"provider"`
|
||||||
@@ -293,6 +299,11 @@ type QueryShareInfoRequest struct {
|
|||||||
InviteCode string `json:"invite_code"`
|
InviteCode string `json:"invite_code"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RecentListRequest struct {
|
||||||
|
Provider string `json:"provider"`
|
||||||
|
Bucket string `json:"bucket"`
|
||||||
|
}
|
||||||
|
|
||||||
type RecentListResponse struct {
|
type RecentListResponse struct {
|
||||||
Records []AllImageDetail `json:"records"`
|
Records []AllImageDetail `json:"records"`
|
||||||
}
|
}
|
||||||
@@ -345,6 +356,15 @@ type RotateCaptchaResponse struct {
|
|||||||
Thumb string `json:"thumb"`
|
Thumb string `json:"thumb"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ShareAlbumRequest struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
ExpireDate string `json:"expire_date"`
|
||||||
|
AccessLimit int64 `json:"access_limit,omitempty"`
|
||||||
|
AccessPassword string `json:"access_password,omitempty"`
|
||||||
|
Provider string `json:"provider"`
|
||||||
|
Bucket string `json:"bucket"`
|
||||||
|
}
|
||||||
|
|
||||||
type ShareImageListMeta struct {
|
type ShareImageListMeta struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
FileName string `json:"file_name"`
|
FileName string `json:"file_name"`
|
||||||
|
@@ -18,6 +18,8 @@ type ScaStorageShare struct {
|
|||||||
ID int64 `gorm:"column:id;type:bigint(20);primaryKey;autoIncrement:true;comment:主键;primary_key" json:"id,string"` // 主键
|
ID int64 `gorm:"column:id;type:bigint(20);primaryKey;autoIncrement:true;comment:主键;primary_key" json:"id,string"` // 主键
|
||||||
UserID string `gorm:"column:user_id;type:varchar(50);comment:用户ID" json:"user_id"` // 用户ID
|
UserID string `gorm:"column:user_id;type:varchar(50);comment:用户ID" json:"user_id"` // 用户ID
|
||||||
AlbumID int64 `gorm:"column:album_id;type:bigint(20);comment:相册ID" json:"album_id"` // 相册ID
|
AlbumID int64 `gorm:"column:album_id;type:bigint(20);comment:相册ID" json:"album_id"` // 相册ID
|
||||||
|
Provider string `gorm:"column:provider;type:varchar(50);comment:存储商" json:"provider"` // 存储商
|
||||||
|
Bucket string `gorm:"column:bucket;type:varchar(50);comment:存储桶" json:"bucket"` // 存储桶
|
||||||
InviteCode string `gorm:"column:invite_code;type:varchar(50);comment:邀请码(用于访问分享链接)" json:"invite_code"` // 邀请码(用于访问分享链接)
|
InviteCode string `gorm:"column:invite_code;type:varchar(50);comment:邀请码(用于访问分享链接)" json:"invite_code"` // 邀请码(用于访问分享链接)
|
||||||
ExpireTime time.Time `gorm:"column:expire_time;type:datetime;comment:过期时间" json:"expire_time"` // 过期时间
|
ExpireTime time.Time `gorm:"column:expire_time;type:datetime;comment:过期时间" json:"expire_time"` // 过期时间
|
||||||
ValidityPeriod int64 `gorm:"column:validity_period;type:int(11);comment:有效期" json:"validity_period"` // 有效期
|
ValidityPeriod int64 `gorm:"column:validity_period;type:int(11);comment:有效期" json:"validity_period"` // 有效期
|
||||||
|
@@ -30,6 +30,8 @@ func newScaStorageShare(db *gorm.DB, opts ...gen.DOOption) scaStorageShare {
|
|||||||
_scaStorageShare.ID = field.NewInt64(tableName, "id")
|
_scaStorageShare.ID = field.NewInt64(tableName, "id")
|
||||||
_scaStorageShare.UserID = field.NewString(tableName, "user_id")
|
_scaStorageShare.UserID = field.NewString(tableName, "user_id")
|
||||||
_scaStorageShare.AlbumID = field.NewInt64(tableName, "album_id")
|
_scaStorageShare.AlbumID = field.NewInt64(tableName, "album_id")
|
||||||
|
_scaStorageShare.Provider = field.NewString(tableName, "provider")
|
||||||
|
_scaStorageShare.Bucket = field.NewString(tableName, "bucket")
|
||||||
_scaStorageShare.InviteCode = field.NewString(tableName, "invite_code")
|
_scaStorageShare.InviteCode = field.NewString(tableName, "invite_code")
|
||||||
_scaStorageShare.ExpireTime = field.NewTime(tableName, "expire_time")
|
_scaStorageShare.ExpireTime = field.NewTime(tableName, "expire_time")
|
||||||
_scaStorageShare.ValidityPeriod = field.NewInt64(tableName, "validity_period")
|
_scaStorageShare.ValidityPeriod = field.NewInt64(tableName, "validity_period")
|
||||||
@@ -55,6 +57,8 @@ type scaStorageShare struct {
|
|||||||
ID field.Int64 // 主键
|
ID field.Int64 // 主键
|
||||||
UserID field.String // 用户ID
|
UserID field.String // 用户ID
|
||||||
AlbumID field.Int64 // 相册ID
|
AlbumID field.Int64 // 相册ID
|
||||||
|
Provider field.String // 存储商
|
||||||
|
Bucket field.String // 存储桶
|
||||||
InviteCode field.String // 邀请码(用于访问分享链接)
|
InviteCode field.String // 邀请码(用于访问分享链接)
|
||||||
ExpireTime field.Time // 过期时间
|
ExpireTime field.Time // 过期时间
|
||||||
ValidityPeriod field.Int64 // 有效期
|
ValidityPeriod field.Int64 // 有效期
|
||||||
@@ -85,6 +89,8 @@ func (s *scaStorageShare) updateTableName(table string) *scaStorageShare {
|
|||||||
s.ID = field.NewInt64(table, "id")
|
s.ID = field.NewInt64(table, "id")
|
||||||
s.UserID = field.NewString(table, "user_id")
|
s.UserID = field.NewString(table, "user_id")
|
||||||
s.AlbumID = field.NewInt64(table, "album_id")
|
s.AlbumID = field.NewInt64(table, "album_id")
|
||||||
|
s.Provider = field.NewString(table, "provider")
|
||||||
|
s.Bucket = field.NewString(table, "bucket")
|
||||||
s.InviteCode = field.NewString(table, "invite_code")
|
s.InviteCode = field.NewString(table, "invite_code")
|
||||||
s.ExpireTime = field.NewTime(table, "expire_time")
|
s.ExpireTime = field.NewTime(table, "expire_time")
|
||||||
s.ValidityPeriod = field.NewInt64(table, "validity_period")
|
s.ValidityPeriod = field.NewInt64(table, "validity_period")
|
||||||
@@ -112,10 +118,12 @@ func (s *scaStorageShare) GetFieldByName(fieldName string) (field.OrderExpr, boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *scaStorageShare) fillFieldMap() {
|
func (s *scaStorageShare) fillFieldMap() {
|
||||||
s.fieldMap = make(map[string]field.Expr, 14)
|
s.fieldMap = make(map[string]field.Expr, 16)
|
||||||
s.fieldMap["id"] = s.ID
|
s.fieldMap["id"] = s.ID
|
||||||
s.fieldMap["user_id"] = s.UserID
|
s.fieldMap["user_id"] = s.UserID
|
||||||
s.fieldMap["album_id"] = s.AlbumID
|
s.fieldMap["album_id"] = s.AlbumID
|
||||||
|
s.fieldMap["provider"] = s.Provider
|
||||||
|
s.fieldMap["bucket"] = s.Bucket
|
||||||
s.fieldMap["invite_code"] = s.InviteCode
|
s.fieldMap["invite_code"] = s.InviteCode
|
||||||
s.fieldMap["expire_time"] = s.ExpireTime
|
s.fieldMap["expire_time"] = s.ExpireTime
|
||||||
s.fieldMap["validity_period"] = s.ValidityPeriod
|
s.fieldMap["validity_period"] = s.ValidityPeriod
|
||||||
|
Reference in New Issue
Block a user