diff --git a/.idea/GOHCache.xml b/.idea/GOHCache.xml
index 3b91227..64b8a2a 100644
--- a/.idea/GOHCache.xml
+++ b/.idea/GOHCache.xml
@@ -164,13 +164,6 @@
-
-
-
-
-
-
-
@@ -228,6 +221,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -376,6 +383,13 @@
+
+
+
+
+
+
+
@@ -793,6 +807,13 @@
+
+
+
+
+
+
+
@@ -1728,7 +1749,7 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2305,6 +2362,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2578,20 +2647,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -2602,7 +2657,7 @@
-
+
@@ -2614,7 +2669,7 @@
-
+
@@ -2626,7 +2681,7 @@
-
+
@@ -2638,7 +2693,7 @@
-
+
@@ -2650,7 +2705,7 @@
-
+
@@ -2662,7 +2717,7 @@
-
+
@@ -2674,7 +2729,7 @@
-
+
@@ -2686,7 +2741,7 @@
-
+
@@ -2698,7 +2753,7 @@
-
+
@@ -2710,7 +2765,7 @@
-
+
@@ -2722,7 +2777,7 @@
-
+
@@ -2734,7 +2789,7 @@
-
+
@@ -2746,7 +2801,7 @@
-
+
@@ -2758,7 +2813,7 @@
-
+
@@ -2770,7 +2825,7 @@
-
+
@@ -2782,7 +2837,7 @@
-
+
@@ -2794,7 +2849,7 @@
-
+
@@ -2813,7 +2868,7 @@
-
+
@@ -2827,7 +2882,7 @@
-
+
@@ -2840,7 +2895,7 @@
-
+
@@ -2853,7 +2908,7 @@
-
+
@@ -2866,7 +2921,7 @@
-
+
@@ -2879,7 +2934,7 @@
-
+
@@ -2892,7 +2947,7 @@
-
+
@@ -2905,7 +2960,7 @@
-
+
@@ -2918,7 +2973,7 @@
-
+
@@ -2931,7 +2986,7 @@
-
+
@@ -2944,7 +2999,7 @@
-
+
@@ -2957,7 +3012,7 @@
-
+
@@ -2970,7 +3025,7 @@
-
+
@@ -2983,7 +3038,7 @@
-
+
@@ -2996,7 +3051,7 @@
-
+
@@ -3009,7 +3064,7 @@
-
+
@@ -3022,7 +3077,7 @@
-
+
@@ -3035,7 +3090,7 @@
-
+
@@ -3822,7 +3877,6 @@
-
@@ -3831,8 +3885,10 @@
+
+
@@ -3854,6 +3910,7 @@
+
@@ -3914,6 +3971,7 @@
+
@@ -3991,6 +4049,6 @@
-
+
\ No newline at end of file
diff --git a/app/auth/api/auth.api b/app/auth/api/auth.api
index 07c268c..532f692 100644
--- a/app/auth/api/auth.api
+++ b/app/auth/api/auth.api
@@ -449,6 +449,74 @@ type (
ModifyFaceTypeResponse {
result string `json:"result"`
}
+ FaceDetailListRequest {
+ FaceID int64 `json:"face_id"`
+ }
+ // 创建相册请求参数
+ AlbumCreateRequest {
+ Name string `json:"name"`
+ }
+ // 创建相册响应参数
+ AlbumCreateResponse {
+ ID int64 `json:"id"`
+ }
+ // 相册列表请求参数
+ AlbumListRequest {
+ Type string `json:"type"`
+ Sort bool `json:"sort"`
+ }
+ // 相册列表响应参数
+ Album {
+ ID int64 `json:"id"`
+ Name string `json:"name"`
+ CreatedAt string `json:"created_at"`
+ Type string `json:"type"`
+ CoverImage string `json:"cover_image"`
+ }
+ AlbumListResponse {
+ Albums []Album `json:"albums"`
+ }
+ // 相册详情请求参数
+ AlbumDetailListRequest {
+ ID int64 `json:"id"`
+ }
+ // 重命名相册请求参数
+ AlbumRenameRequest {
+ ID int64 `json:"id"`
+ Name string `json:"name"`
+ }
+ // 重命名相册响应参数
+ AlbumRenameResponse {
+ ID int64 `json:"id"`
+ Name string `json:"name"`
+ }
+ // 删除相册请求参数
+ AlbumDeleteRequest {
+ ID int64 `json:"id"`
+ }
+ // 所有图片列表请求参数
+ AllImageListRequest {
+ Type string `json:"type"`
+ Sort bool `json:"sort"`
+ Provider string `json:"provider"`
+ Bucket string `json:"bucket"`
+ }
+ // 所有图片列表响应参数
+ ImageMeta {
+ ID int64 `json:"id"`
+ fileName string `json:"file_name"`
+ filePath string `json:"file_path"`
+ URL string `json:"url"`
+ fileSize string `json:"file_size"`
+ CreatedAt string `json:"created_at"`
+ }
+ AllImageDetail {
+ Date string `json:"date"`
+ list []ImageMeta `json:"list"`
+ }
+ AllImageListResponse {
+ records []AllImageDetail `json:"records"`
+ }
)
// 文件上传
@@ -483,5 +551,33 @@ service auth {
// 修改人脸样本类型
@handler modifyFaceLibraryType
post /face/sample/modify/type (ModifyFaceTypeRequest) returns (ModifyFaceTypeResponse)
+
+ // 获取人脸详情列表 (暂定)
+ @handler getFaceDetailList
+ post /face/detail/list (FaceDetailListRequest) returns (string)
+
+ // 创建相册
+ @handler createAlbum
+ post /album/create (AlbumCreateRequest) returns (AlbumCreateResponse)
+
+ // 获取相册列表
+ @handler getAlbumList
+ post /album/list (AlbumListRequest) returns (AlbumListResponse)
+
+ // 获取相册详情(暂定)
+ @handler getAlbumDetail
+ post /album/detail/list (AlbumDetailListRequest) returns (string)
+
+ // 重命名相册
+ @handler renameAlbum
+ post /album/rename (AlbumRenameRequest) returns (AlbumRenameResponse)
+
+ // 删除相册
+ @handler deleteAlbum
+ post /album/delete (AlbumDeleteRequest) returns (string)
+
+ // 获取所有图片列表
+ @handler queryAllImageList
+ post /image/all/list (AllImageListRequest) returns (AllImageListResponse)
}
diff --git a/app/auth/api/etc/auth.yaml b/app/auth/api/etc/auth.yaml
index d1c7aa4..5519c30 100644
--- a/app/auth/api/etc/auth.yaml
+++ b/app/auth/api/etc/auth.yaml
@@ -72,18 +72,6 @@ Mysql:
MaxOpenConn: 10
# 最大空闲连接数
MaxIdleConn: 5
-# Mongo 配置
-Mongo:
- # MongoDB 地址
- Uri: mongodb://1.95.0.111:27017
- # MongoDB 用户名
- Username: landaiqing
- # MongoDB 密码
- Password: LDQ20020618xxx
- # MongoDB 数据库
- Database: schisandra-cloud-album
- # MongoDB 认证源
- AuthSource: admin
# Auth 配置
Auth:
# 访问密钥
diff --git a/app/auth/api/internal/config/config.go b/app/auth/api/internal/config/config.go
index b91c4cd..6d8590e 100644
--- a/app/auth/api/internal/config/config.go
+++ b/app/auth/api/internal/config/config.go
@@ -23,13 +23,6 @@ type Config struct {
MaxOpenConn int
MaxIdleConn int
}
- Mongo struct {
- Uri string
- Username string
- Password string
- AuthSource string
- Database string
- }
Redis struct {
Host string
Pass string
diff --git a/app/auth/api/internal/handler/file/upload_file_handler.go b/app/auth/api/internal/handler/file/upload_file_handler.go
deleted file mode 100644
index 957f52a..0000000
--- a/app/auth/api/internal/handler/file/upload_file_handler.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package file
-
-import (
- "net/http"
- "schisandra-album-cloud-microservices/app/auth/api/internal/logic/storage"
- "schisandra-album-cloud-microservices/common/xhttp"
-
- "schisandra-album-cloud-microservices/app/auth/api/internal/svc"
-)
-
-func UploadFileHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
- return func(w http.ResponseWriter, r *http.Request) {
- l := storage.NewUploadFileLogic(r.Context(), svcCtx)
- resp, err := l.UploadFile(r)
- if err != nil {
- xhttp.JsonBaseResponseCtx(r.Context(), w, err)
- } else {
- xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
- }
- }
-}
diff --git a/app/auth/api/internal/handler/routes.go b/app/auth/api/internal/handler/routes.go
index fca193a..3fc779f 100644
--- a/app/auth/api/internal/handler/routes.go
+++ b/app/auth/api/internal/handler/routes.go
@@ -188,11 +188,41 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware, serverCtx.NonceMiddleware},
[]rest.Route{
+ {
+ Method: http.MethodPost,
+ Path: "/album/create",
+ Handler: storage.CreateAlbumHandler(serverCtx),
+ },
+ {
+ Method: http.MethodPost,
+ Path: "/album/delete",
+ Handler: storage.DeleteAlbumHandler(serverCtx),
+ },
+ {
+ Method: http.MethodPost,
+ Path: "/album/detail/list",
+ Handler: storage.GetAlbumDetailHandler(serverCtx),
+ },
+ {
+ Method: http.MethodPost,
+ Path: "/album/list",
+ Handler: storage.GetAlbumListHandler(serverCtx),
+ },
+ {
+ Method: http.MethodPost,
+ Path: "/album/rename",
+ Handler: storage.RenameAlbumHandler(serverCtx),
+ },
{
Method: http.MethodPost,
Path: "/config",
Handler: storage.SetStorageConfigHandler(serverCtx),
},
+ {
+ Method: http.MethodPost,
+ Path: "/face/detail/list",
+ Handler: storage.GetFaceDetailListHandler(serverCtx),
+ },
{
Method: http.MethodPost,
Path: "/face/sample/list",
@@ -208,6 +238,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/face/sample/modify/type",
Handler: storage.ModifyFaceLibraryTypeHandler(serverCtx),
},
+ {
+ Method: http.MethodPost,
+ Path: "/image/all/list",
+ Handler: storage.QueryAllImageListHandler(serverCtx),
+ },
{
Method: http.MethodPost,
Path: "/uploads",
diff --git a/app/auth/api/internal/handler/file/set_storage_config_handler.go b/app/auth/api/internal/handler/storage/create_album_handler.go
similarity index 73%
rename from app/auth/api/internal/handler/file/set_storage_config_handler.go
rename to app/auth/api/internal/handler/storage/create_album_handler.go
index c01385e..fe78d4e 100644
--- a/app/auth/api/internal/handler/file/set_storage_config_handler.go
+++ b/app/auth/api/internal/handler/storage/create_album_handler.go
@@ -1,25 +1,25 @@
-package file
+package storage
import (
"net/http"
- "schisandra-album-cloud-microservices/app/auth/api/internal/logic/storage"
"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 SetStorageConfigHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+func CreateAlbumHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
- var req types.StorageConfigRequest
+ var req types.AlbumCreateRequest
if err := httpx.Parse(r, &req); err != nil {
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
return
}
- l := storage.NewSetStorageConfigLogic(r.Context(), svcCtx)
- resp, err := l.SetStorageConfig(&req)
+ l := storage.NewCreateAlbumLogic(r.Context(), svcCtx)
+ resp, err := l.CreateAlbum(&req)
if err != nil {
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
} else {
diff --git a/app/auth/api/internal/handler/storage/delete_album_handler.go b/app/auth/api/internal/handler/storage/delete_album_handler.go
new file mode 100644
index 0000000..69868cd
--- /dev/null
+++ b/app/auth/api/internal/handler/storage/delete_album_handler.go
@@ -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 DeleteAlbumHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ var req types.AlbumDeleteRequest
+ if err := httpx.Parse(r, &req); err != nil {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, err)
+ return
+ }
+
+ l := storage.NewDeleteAlbumLogic(r.Context(), svcCtx)
+ resp, err := l.DeleteAlbum(&req)
+ if err != nil {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, err)
+ } else {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
+ }
+ }
+}
diff --git a/app/auth/api/internal/handler/storage/get_album_detail_handler.go b/app/auth/api/internal/handler/storage/get_album_detail_handler.go
new file mode 100644
index 0000000..6d7b3b6
--- /dev/null
+++ b/app/auth/api/internal/handler/storage/get_album_detail_handler.go
@@ -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 GetAlbumDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ var req types.AlbumDetailListRequest
+ if err := httpx.Parse(r, &req); err != nil {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, err)
+ return
+ }
+
+ l := storage.NewGetAlbumDetailLogic(r.Context(), svcCtx)
+ resp, err := l.GetAlbumDetail(&req)
+ if err != nil {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, err)
+ } else {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
+ }
+ }
+}
diff --git a/app/auth/api/internal/handler/storage/get_album_list_handler.go b/app/auth/api/internal/handler/storage/get_album_list_handler.go
new file mode 100644
index 0000000..08bf4de
--- /dev/null
+++ b/app/auth/api/internal/handler/storage/get_album_list_handler.go
@@ -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 GetAlbumListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ var req types.AlbumListRequest
+ if err := httpx.Parse(r, &req); err != nil {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, err)
+ return
+ }
+
+ l := storage.NewGetAlbumListLogic(r.Context(), svcCtx)
+ resp, err := l.GetAlbumList(&req)
+ if err != nil {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, err)
+ } else {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
+ }
+ }
+}
diff --git a/app/auth/api/internal/handler/storage/get_face_detail_list_handler.go b/app/auth/api/internal/handler/storage/get_face_detail_list_handler.go
new file mode 100644
index 0000000..446844b
--- /dev/null
+++ b/app/auth/api/internal/handler/storage/get_face_detail_list_handler.go
@@ -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 GetFaceDetailListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ var req types.FaceDetailListRequest
+ if err := httpx.Parse(r, &req); err != nil {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, err)
+ return
+ }
+
+ l := storage.NewGetFaceDetailListLogic(r.Context(), svcCtx)
+ resp, err := l.GetFaceDetailList(&req)
+ if err != nil {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, err)
+ } else {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
+ }
+ }
+}
diff --git a/app/auth/api/internal/handler/storage/query_all_image_list_handler.go b/app/auth/api/internal/handler/storage/query_all_image_list_handler.go
new file mode 100644
index 0000000..0e309ab
--- /dev/null
+++ b/app/auth/api/internal/handler/storage/query_all_image_list_handler.go
@@ -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 QueryAllImageListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ var req types.AllImageListRequest
+ if err := httpx.Parse(r, &req); err != nil {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, err)
+ return
+ }
+
+ l := storage.NewQueryAllImageListLogic(r.Context(), svcCtx)
+ resp, err := l.QueryAllImageList(&req)
+ if err != nil {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, err)
+ } else {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
+ }
+ }
+}
diff --git a/app/auth/api/internal/handler/storage/rename_album_handler.go b/app/auth/api/internal/handler/storage/rename_album_handler.go
new file mode 100644
index 0000000..a83e25f
--- /dev/null
+++ b/app/auth/api/internal/handler/storage/rename_album_handler.go
@@ -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 RenameAlbumHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ var req types.AlbumRenameRequest
+ if err := httpx.Parse(r, &req); err != nil {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, err)
+ return
+ }
+
+ l := storage.NewRenameAlbumLogic(r.Context(), svcCtx)
+ resp, err := l.RenameAlbum(&req)
+ if err != nil {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, err)
+ } else {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
+ }
+ }
+}
diff --git a/app/auth/api/internal/handler/storage/upload_file_handler.go b/app/auth/api/internal/handler/storage/upload_file_handler.go
index c1b1f0b..c8d8d58 100644
--- a/app/auth/api/internal/handler/storage/upload_file_handler.go
+++ b/app/auth/api/internal/handler/storage/upload_file_handler.go
@@ -11,6 +11,10 @@ import (
func UploadFileHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := storage.NewUploadFileLogic(r.Context(), svcCtx)
+ err := r.ParseMultipartForm(50 << 20)
+ if err != nil {
+ xhttp.JsonBaseResponseCtx(r.Context(), w, err)
+ }
resp, err := l.UploadFile(r)
if err != nil {
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
diff --git a/app/auth/api/internal/logic/storage/create_album_logic.go b/app/auth/api/internal/logic/storage/create_album_logic.go
new file mode 100644
index 0000000..b424730
--- /dev/null
+++ b/app/auth/api/internal/logic/storage/create_album_logic.go
@@ -0,0 +1,43 @@
+package storage
+
+import (
+ "context"
+ "errors"
+ "schisandra-album-cloud-microservices/app/auth/model/mysql/model"
+
+ "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 CreateAlbumLogic struct {
+ logx.Logger
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+}
+
+func NewCreateAlbumLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateAlbumLogic {
+ return &CreateAlbumLogic{
+ Logger: logx.WithContext(ctx),
+ ctx: ctx,
+ svcCtx: svcCtx,
+ }
+}
+
+func (l *CreateAlbumLogic) CreateAlbum(req *types.AlbumCreateRequest) (resp *types.AlbumCreateResponse, err error) {
+ uid, ok := l.ctx.Value("user_id").(string)
+ if !ok {
+ return nil, errors.New("user_id not found")
+ }
+ storageAlbum := &model.ScaStorageAlbum{
+ UserID: uid,
+ AlbumName: req.Name,
+ AlbumType: "0",
+ }
+ err = l.svcCtx.DB.ScaStorageAlbum.Create(storageAlbum)
+ if err != nil {
+ return nil, err
+ }
+ return &types.AlbumCreateResponse{ID: storageAlbum.ID}, nil
+}
diff --git a/app/auth/api/internal/logic/storage/delete_album_logic.go b/app/auth/api/internal/logic/storage/delete_album_logic.go
new file mode 100644
index 0000000..fe049d0
--- /dev/null
+++ b/app/auth/api/internal/logic/storage/delete_album_logic.go
@@ -0,0 +1,47 @@
+package storage
+
+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 DeleteAlbumLogic struct {
+ logx.Logger
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+}
+
+//43454A
+
+func NewDeleteAlbumLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteAlbumLogic {
+ return &DeleteAlbumLogic{
+ Logger: logx.WithContext(ctx),
+ ctx: ctx,
+ svcCtx: svcCtx,
+ }
+}
+
+func (l *DeleteAlbumLogic) DeleteAlbum(req *types.AlbumDeleteRequest) (resp string, err error) {
+ uid, ok := l.ctx.Value("user_id").(string)
+ if !ok {
+ 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()
+ if err != nil {
+ return "", err
+ }
+ if info.RowsAffected == 0 {
+ return "", errors.New("album not found")
+ }
+ storageInfo := l.svcCtx.DB.ScaStorageInfo
+ _, err = storageInfo.Where(storageInfo.AlbumID.Eq(req.ID), storageInfo.UserID.Eq(uid)).Update(storageInfo.AlbumID, nil)
+ if err != nil {
+ return "", err
+ }
+ return "success", nil
+}
diff --git a/app/auth/api/internal/logic/storage/get_album_detail_logic.go b/app/auth/api/internal/logic/storage/get_album_detail_logic.go
new file mode 100644
index 0000000..cee457d
--- /dev/null
+++ b/app/auth/api/internal/logic/storage/get_album_detail_logic.go
@@ -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 GetAlbumDetailLogic struct {
+ logx.Logger
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+}
+
+func NewGetAlbumDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAlbumDetailLogic {
+ return &GetAlbumDetailLogic{
+ Logger: logx.WithContext(ctx),
+ ctx: ctx,
+ svcCtx: svcCtx,
+ }
+}
+
+func (l *GetAlbumDetailLogic) GetAlbumDetail(req *types.AlbumDetailListRequest) (resp string, err error) {
+ // todo: add your logic here and delete this line
+
+ return
+}
diff --git a/app/auth/api/internal/logic/storage/get_album_list_logic.go b/app/auth/api/internal/logic/storage/get_album_list_logic.go
new file mode 100644
index 0000000..9c3aed1
--- /dev/null
+++ b/app/auth/api/internal/logic/storage/get_album_list_logic.go
@@ -0,0 +1,57 @@
+package storage
+
+import (
+ "context"
+ "errors"
+ "gorm.io/gen/field"
+
+ "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 GetAlbumListLogic struct {
+ logx.Logger
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+}
+
+func NewGetAlbumListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAlbumListLogic {
+ return &GetAlbumListLogic{
+ Logger: logx.WithContext(ctx),
+ ctx: ctx,
+ svcCtx: svcCtx,
+ }
+}
+
+func (l *GetAlbumListLogic) GetAlbumList(req *types.AlbumListRequest) (resp *types.AlbumListResponse, err error) {
+ uid, ok := l.ctx.Value("user_id").(string)
+ if !ok {
+ return nil, errors.New("user_id not found")
+ }
+ var orderConditions []field.Expr
+ storageAlbum := l.svcCtx.DB.ScaStorageAlbum
+ if req.Sort {
+ orderConditions = append(orderConditions, storageAlbum.CreatedAt.Desc())
+ } else {
+ orderConditions = append(orderConditions, storageAlbum.AlbumName.Desc())
+ }
+ albums, err := storageAlbum.Where(storageAlbum.UserID.Eq(uid), storageAlbum.AlbumType.Eq(req.Type)).Order(orderConditions...).Find()
+ if err != nil {
+ return nil, err
+ }
+ var albumList []types.Album
+ for _, album := range albums {
+ albumList = append(albumList, types.Album{
+ ID: album.ID,
+ Name: album.AlbumName,
+ Type: album.AlbumType,
+ CoverImage: album.CoverImage,
+ CreatedAt: album.CreatedAt.Format("2006-01-02"),
+ })
+ }
+ return &types.AlbumListResponse{
+ Albums: albumList,
+ }, nil
+}
diff --git a/app/auth/api/internal/logic/storage/get_face_detail_list_logic.go b/app/auth/api/internal/logic/storage/get_face_detail_list_logic.go
new file mode 100644
index 0000000..f5c0d0c
--- /dev/null
+++ b/app/auth/api/internal/logic/storage/get_face_detail_list_logic.go
@@ -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 GetFaceDetailListLogic struct {
+ logx.Logger
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+}
+
+func NewGetFaceDetailListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetFaceDetailListLogic {
+ return &GetFaceDetailListLogic{
+ Logger: logx.WithContext(ctx),
+ ctx: ctx,
+ svcCtx: svcCtx,
+ }
+}
+
+func (l *GetFaceDetailListLogic) GetFaceDetailList(req *types.FaceDetailListRequest) (resp string, err error) {
+ // todo: add your logic here and delete this line
+
+ return
+}
diff --git a/app/auth/api/internal/logic/storage/query_all_image_list_logic.go b/app/auth/api/internal/logic/storage/query_all_image_list_logic.go
new file mode 100644
index 0000000..f296a66
--- /dev/null
+++ b/app/auth/api/internal/logic/storage/query_all_image_list_logic.go
@@ -0,0 +1,201 @@
+package storage
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "github.com/redis/go-redis/v9"
+ "math/rand"
+ "schisandra-album-cloud-microservices/app/auth/api/internal/svc"
+ "schisandra-album-cloud-microservices/app/auth/api/internal/types"
+ "schisandra-album-cloud-microservices/app/auth/model/mysql/model"
+ "schisandra-album-cloud-microservices/app/auth/model/mysql/query"
+ "schisandra-album-cloud-microservices/common/constant"
+ "schisandra-album-cloud-microservices/common/encrypt"
+ storageConfig "schisandra-album-cloud-microservices/common/storage/config"
+ "sync"
+ "time"
+
+ "github.com/zeromicro/go-zero/core/logx"
+)
+
+type QueryAllImageListLogic struct {
+ logx.Logger
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+}
+
+func NewQueryAllImageListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryAllImageListLogic {
+ return &QueryAllImageListLogic{
+ Logger: logx.WithContext(ctx),
+ ctx: ctx,
+ svcCtx: svcCtx,
+ }
+}
+
+func (l *QueryAllImageListLogic) QueryAllImageList(req *types.AllImageListRequest) (resp *types.AllImageListResponse, err error) {
+ uid, ok := l.ctx.Value("user_id").(string)
+ if !ok {
+ return nil, errors.New("user_id not found")
+ }
+ // 从缓存获取数据
+ cacheKey := fmt.Sprintf("%s%s:%s:%s:%t", constant.ImageListPrefix, uid, req.Provider, req.Bucket, req.Sort)
+ // 尝试从缓存获取
+ cachedResult, err := l.svcCtx.RedisClient.Get(l.ctx, cacheKey).Result()
+ if err == nil {
+ var cachedResponse types.AllImageListResponse
+ if err := json.Unmarshal([]byte(cachedResult), &cachedResponse); err == nil {
+ return &cachedResponse, nil
+ }
+ logx.Error("Failed to unmarshal cached image list:", err)
+ return nil, errors.New("get cached image list failed")
+ } else if !errors.Is(err, redis.Nil) {
+ logx.Error("Redis error:", err)
+ return nil, errors.New("get cached image list failed")
+ }
+
+ // 缓存未命中,从数据库中查询
+ storageInfo := l.svcCtx.DB.ScaStorageInfo
+ // 数据库查询文件信息列表
+ var storageInfoQuery query.IScaStorageInfoDo
+ if req.Sort {
+ storageInfoQuery = storageInfo.Where(storageInfo.UserID.Eq(uid), storageInfo.Provider.Eq(req.Provider), storageInfo.Bucket.Eq(req.Bucket), storageInfo.AlbumID.IsNull()).Order(storageInfo.CreatedAt.Desc())
+ } else {
+ storageInfoQuery = storageInfo.Where(storageInfo.UserID.Eq(uid), storageInfo.Provider.Eq(req.Provider), storageInfo.Bucket.Eq(req.Bucket)).Order(storageInfo.CreatedAt.Desc())
+ }
+ storageInfoList, err := storageInfoQuery.Find()
+ if err != nil {
+ return nil, err
+ }
+ if len(storageInfoList) == 0 {
+ return &types.AllImageListResponse{}, nil
+ }
+
+ // 加载用户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")
+ }
+
+ // 按日期进行分组
+ var wg sync.WaitGroup
+ groupedImages := sync.Map{}
+
+ for _, dbFileInfo := range storageInfoList {
+ wg.Add(1)
+ go func(dbFileInfo *model.ScaStorageInfo) {
+ defer wg.Done()
+ date := dbFileInfo.CreatedAt.Format("2006-01-02")
+ url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Hour*24*7)
+ if err != nil {
+ logx.Error(err)
+ return
+ }
+ // 使用 Load 或 Store 确保原子操作
+ value, _ := groupedImages.LoadOrStore(date, []types.ImageMeta{})
+ images := value.([]types.ImageMeta)
+
+ images = append(images, types.ImageMeta{
+ ID: dbFileInfo.ID,
+ FileName: dbFileInfo.FileName,
+ FilePath: dbFileInfo.Path,
+ URL: url,
+ FileSize: dbFileInfo.FileSize,
+ CreatedAt: dbFileInfo.CreatedAt.Format("2006-01-02 15:04:05"),
+ })
+
+ // 重新存储更新后的图像列表
+ groupedImages.Store(date, images)
+ }(dbFileInfo)
+ }
+ wg.Wait()
+ var imageList []types.AllImageDetail
+ groupedImages.Range(func(key, value interface{}) bool {
+ imageList = append(imageList, types.AllImageDetail{
+ Date: key.(string),
+ List: value.([]types.ImageMeta),
+ })
+ return true
+ })
+ resp = &types.AllImageListResponse{
+ Records: imageList,
+ }
+ // 缓存结果
+ if data, err := json.Marshal(resp); err == nil {
+ expireTime := 7*24*time.Hour - time.Duration(rand.Intn(60))*time.Minute
+ 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 *QueryAllImageListLogic) 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.Type,
+ Endpoint: config.Endpoint,
+ AccessKey: accessKey,
+ SecretKey: secretKey,
+ BucketName: config.Bucket,
+ Region: config.Region,
+ }, nil
+}
+
+// 从缓存或数据库中获取 OSS 配置
+func (l *QueryAllImageListLogic) 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.Type.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
+}
diff --git a/app/auth/api/internal/logic/storage/rename_album_logic.go b/app/auth/api/internal/logic/storage/rename_album_logic.go
new file mode 100644
index 0000000..554ccba
--- /dev/null
+++ b/app/auth/api/internal/logic/storage/rename_album_logic.go
@@ -0,0 +1,44 @@
+package storage
+
+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 RenameAlbumLogic struct {
+ logx.Logger
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+}
+
+func NewRenameAlbumLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RenameAlbumLogic {
+ return &RenameAlbumLogic{
+ Logger: logx.WithContext(ctx),
+ ctx: ctx,
+ svcCtx: svcCtx,
+ }
+}
+
+func (l *RenameAlbumLogic) RenameAlbum(req *types.AlbumRenameRequest) (resp *types.AlbumRenameResponse, err error) {
+ uid, ok := l.ctx.Value("user_id").(string)
+ if !ok {
+ return nil, errors.New("user_id not found")
+ }
+ storageAlbum := l.svcCtx.DB.ScaStorageAlbum
+ info, err := storageAlbum.Where(storageAlbum.ID.Eq(req.ID), storageAlbum.UserID.Eq(uid)).Update(storageAlbum.AlbumName, req.Name)
+ if err != nil {
+ return nil, err
+ }
+ if info.RowsAffected == 0 {
+ return nil, errors.New("album not found")
+ }
+ return &types.AlbumRenameResponse{
+ ID: req.ID,
+ Name: req.Name,
+ }, nil
+}
diff --git a/app/auth/api/internal/logic/storage/upload_file_logic.go b/app/auth/api/internal/logic/storage/upload_file_logic.go
index 619f738..3812b5b 100644
--- a/app/auth/api/internal/logic/storage/upload_file_logic.go
+++ b/app/auth/api/internal/logic/storage/upload_file_logic.go
@@ -5,14 +5,19 @@ import (
"encoding/json"
"errors"
"fmt"
+ "github.com/ccpwcn/kgo"
+ "github.com/redis/go-redis/v9"
"github.com/zeromicro/go-zero/core/logx"
"io"
"mime/multipart"
"net/http"
+ "path"
+ "path/filepath"
"schisandra-album-cloud-microservices/app/aisvc/rpc/pb"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
+ "schisandra-album-cloud-microservices/common/constant"
"schisandra-album-cloud-microservices/common/encrypt"
"schisandra-album-cloud-microservices/common/gao_map"
"schisandra-album-cloud-microservices/common/storage/config"
@@ -47,6 +52,7 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
if err != nil {
return "", err
}
+
defer func(file multipart.File) {
_ = file.Close()
}(file)
@@ -102,16 +108,23 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
}
// 上传文件到 OSS
- bucket, provider, err := l.uploadFileToOSS(uid, header, file)
+ // 重新设置文件指针到文件开头
+ if _, err = file.Seek(0, 0); err != nil {
+ return "", err
+ }
+ bucket, provider, filePath, err := l.uploadFileToOSS(uid, header, file, result)
if err != nil {
return "", err
}
// 将 EXIF 和文件信息存入数据库
- if err = l.saveFileInfoToDB(uid, bucket, provider, header, result, originalDateTime, gpsString, locationString, exif, faceId, className); err != nil {
+ if err = l.saveFileInfoToDB(uid, bucket, provider, header, result, originalDateTime, gpsString, locationString, exif, faceId, className, filePath); err != nil {
return "", err
}
+ // 删除缓存
+ l.afterImageUpload(uid, provider, bucket)
+
return "success", nil
}
@@ -124,6 +137,22 @@ func (l *UploadFileLogic) getUserID() (string, error) {
return uid, nil
}
+// 在UploadImageLogic或其他需要使缓存失效的逻辑中添加:
+func (l *UploadFileLogic) afterImageUpload(uid, provider, bucket string) {
+ // 构造所有可能的缓存键组合(sort为true/false)
+ keysToDelete := []string{
+ fmt.Sprintf("%s%s:%s:%s:true", constant.ImageListPrefix, uid, provider, bucket),
+ fmt.Sprintf("%s%s:%s:%s:false", constant.ImageListPrefix, uid, provider, bucket),
+ }
+
+ // 批量删除缓存
+ for _, key := range keysToDelete {
+ if err := l.svcCtx.RedisClient.Del(l.ctx, key).Err(); err != nil {
+ logx.Errorf("Failed to delete cache key %s: %v", key, err)
+ }
+ }
+}
+
// 解析上传的文件
func (l *UploadFileLogic) getUploadedFile(r *http.Request) (multipart.File, *multipart.FileHeader, error) {
file, header, err := r.FormFile("file")
@@ -224,45 +253,34 @@ func (l *UploadFileLogic) getGeoLocation(latitude, longitude float64) (string, s
}
// 上传文件到 OSS
-func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHeader, file multipart.File) (string, string, error) {
- ossConfig := l.svcCtx.DB.ScaStorageConfig
- dbConfig, err := ossConfig.Where(ossConfig.UserID.Eq(uid)).First()
+func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHeader, file multipart.File, result types.File) (string, string, string, error) {
+ cacheKey := constant.UserOssConfigPrefix + uid + ":" + result.Provider
+ ossConfig, err := l.getOssConfigFromCacheOrDb(cacheKey, uid, result.Provider)
if err != nil {
- return "", "", errors.New("oss config not found")
+ return "", "", "", errors.New("get oss config failed")
+ }
+ service, err := l.svcCtx.StorageManager.GetStorage(uid, ossConfig)
+ if err != nil {
+ return "", "", "", errors.New("get storage failed")
}
- accessKey, err := encrypt.Decrypt(dbConfig.AccessKey, l.svcCtx.Config.Encrypt.Key)
- if err != nil {
- return "", "", errors.New("decrypt access key failed")
- }
- secretKey, err := encrypt.Decrypt(dbConfig.SecretKey, l.svcCtx.Config.Encrypt.Key)
- if err != nil {
- return "", "", errors.New("decrypt secret key failed")
- }
+ objectKey := path.Join(
+ uid,
+ time.Now().Format("2006/01"), // 按年/月划分目录
+ fmt.Sprintf("%s_%s%s", strings.TrimSuffix(header.Filename, filepath.Ext(header.Filename)), kgo.SimpleUuid(), filepath.Ext(header.Filename)),
+ )
- storageConfig := &config.StorageConfig{
- Provider: dbConfig.Type,
- Endpoint: dbConfig.Endpoint,
- AccessKey: accessKey,
- SecretKey: secretKey,
- BucketName: dbConfig.Bucket,
- Region: dbConfig.Region,
- }
-
- service, err := l.svcCtx.StorageManager.GetStorage(uid, storageConfig)
+ _, err = service.UploadFileSimple(l.ctx, ossConfig.BucketName, objectKey, file, map[string]string{
+ "Content-Type": header.Header.Get("Content-Type"),
+ })
if err != nil {
- return "", "", errors.New("get storage failed")
+ return "", "", "", errors.New("upload file failed")
}
-
- _, err = service.UploadFileSimple(l.ctx, dbConfig.Bucket, header.Filename, file, map[string]string{})
- if err != nil {
- return "", "", errors.New("upload file failed")
- }
- return dbConfig.Bucket, dbConfig.Type, nil
+ return ossConfig.BucketName, ossConfig.Provider, objectKey, nil
}
// 将 EXIF 和文件信息存入数据库
-func (l *UploadFileLogic) saveFileInfoToDB(uid, bucket, provider string, header *multipart.FileHeader, result types.File, originalDateTime, gpsString, locationString string, exif map[string]interface{}, faceId int64, className string) error {
+func (l *UploadFileLogic) saveFileInfoToDB(uid, bucket, provider string, header *multipart.FileHeader, result types.File, originalDateTime, gpsString, locationString string, exif map[string]interface{}, faceId int64, className, filePath string) error {
exifJSON, err := json.Marshal(exif)
if err != nil {
return errors.New("marshal exif failed")
@@ -278,6 +296,7 @@ func (l *UploadFileLogic) saveFileInfoToDB(uid, bucket, provider string, header
FileName: header.Filename,
FileSize: strconv.FormatInt(header.Size, 10),
FileType: result.FileType,
+ Path: filePath,
Landscape: landscape,
Objects: strings.Join(result.ObjectArray, ", "),
Anime: strconv.FormatBool(result.IsAnime),
@@ -297,3 +316,63 @@ func (l *UploadFileLogic) saveFileInfoToDB(uid, bucket, provider string, header
}
return nil
}
+
+// 提取解密操作为函数
+func (l *UploadFileLogic) decryptConfig(dbConfig *model.ScaStorageConfig) (*config.StorageConfig, error) {
+ accessKey, err := encrypt.Decrypt(dbConfig.AccessKey, l.svcCtx.Config.Encrypt.Key)
+ if err != nil {
+ return nil, errors.New("decrypt access key failed")
+ }
+ secretKey, err := encrypt.Decrypt(dbConfig.SecretKey, l.svcCtx.Config.Encrypt.Key)
+ if err != nil {
+ return nil, errors.New("decrypt secret key failed")
+ }
+ return &config.StorageConfig{
+ Provider: dbConfig.Type,
+ Endpoint: dbConfig.Endpoint,
+ AccessKey: accessKey,
+ SecretKey: secretKey,
+ BucketName: dbConfig.Bucket,
+ Region: dbConfig.Region,
+ }, nil
+}
+
+// 从缓存或数据库中获取 OSS 配置
+func (l *UploadFileLogic) getOssConfigFromCacheOrDb(cacheKey, uid, provider string) (*config.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 *config.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.Type.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
+}
diff --git a/app/auth/api/internal/types/file.go b/app/auth/api/internal/types/file.go
index 7079cf7..918cf0d 100644
--- a/app/auth/api/internal/types/file.go
+++ b/app/auth/api/internal/types/file.go
@@ -2,6 +2,8 @@ package types
// File represents a file uploaded by the user.
type File struct {
+ Provider string `json:"provider"`
+ Bucket string `json:"bucket"`
FileType string `json:"fileType"`
IsAnime bool `json:"isAnime"`
ObjectArray []string `json:"objectArray"`
diff --git a/app/auth/api/internal/types/types.go b/app/auth/api/internal/types/types.go
index ac7e9c2..d2d0d7c 100644
--- a/app/auth/api/internal/types/types.go
+++ b/app/auth/api/internal/types/types.go
@@ -11,6 +11,65 @@ type AccountLoginRequest struct {
Key string `json:"key"`
}
+type Album struct {
+ ID int64 `json:"id"`
+ Name string `json:"name"`
+ CreatedAt string `json:"created_at"`
+ Type string `json:"type"`
+ CoverImage string `json:"cover_image"`
+}
+
+type AlbumCreateRequest struct {
+ Name string `json:"name"`
+}
+
+type AlbumCreateResponse struct {
+ ID int64 `json:"id"`
+}
+
+type AlbumDeleteRequest struct {
+ ID int64 `json:"id"`
+}
+
+type AlbumDetailListRequest struct {
+ ID int64 `json:"id"`
+}
+
+type AlbumListRequest struct {
+ Type string `json:"type"`
+ Sort bool `json:"sort"`
+}
+
+type AlbumListResponse struct {
+ Albums []Album `json:"albums"`
+}
+
+type AlbumRenameRequest struct {
+ ID int64 `json:"id"`
+ Name string `json:"name"`
+}
+
+type AlbumRenameResponse struct {
+ ID int64 `json:"id"`
+ Name string `json:"name"`
+}
+
+type AllImageDetail struct {
+ Date string `json:"date"`
+ List []ImageMeta `json:"list"`
+}
+
+type AllImageListRequest struct {
+ Type string `json:"type"`
+ Sort bool `json:"sort"`
+ Provider string `json:"provider"`
+ Bucket string `json:"bucket"`
+}
+
+type AllImageListResponse struct {
+ Records []AllImageDetail `json:"records"`
+}
+
type CommentContent struct {
NickName string `json:"nickname"`
Avatar string `json:"avatar"`
@@ -82,6 +141,10 @@ type CommentResponse struct {
ReplyTo int64 `json:"reply_to,omitempty"`
}
+type FaceDetailListRequest struct {
+ FaceID int64 `json:"face_id"`
+}
+
type FaceSampleLibrary struct {
ID int64 `json:"id"`
FaceName string `json:"face_name"`
@@ -96,6 +159,15 @@ type FaceSampleLibraryListResponse struct {
Faces []FaceSampleLibrary `json:"faces"`
}
+type ImageMeta struct {
+ ID int64 `json:"id"`
+ FileName string `json:"file_name"`
+ FilePath string `json:"file_path"`
+ URL string `json:"url"`
+ FileSize string `json:"file_size"`
+ CreatedAt string `json:"created_at"`
+}
+
type LoginResponse struct {
AccessToken string `json:"access_token"`
ExpireAt int64 `json:"expire_at"`
diff --git a/app/auth/model/mysql/model/sca_storage_album.gen.go b/app/auth/model/mysql/model/sca_storage_album.gen.go
index 113a009..b0e82c3 100644
--- a/app/auth/model/mysql/model/sca_storage_album.gen.go
+++ b/app/auth/model/mysql/model/sca_storage_album.gen.go
@@ -14,13 +14,14 @@ const TableNameScaStorageAlbum = "sca_storage_album"
// ScaStorageAlbum mapped from table
type ScaStorageAlbum struct {
- 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
- AlbumName string `gorm:"column:album_name;type:varchar(50);comment:相册名称" json:"album_name"` // 相册名称
- AlbumType string `gorm:"column:album_type;type:varchar(50);comment:相册类型" json:"album_type"` // 相册类型
- CreatedAt time.Time `gorm:"column:created_at;type:timestamp;autoCreateTime;comment:创建时间" json:"created_at"` // 创建时间
- UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp;autoUpdateTime;comment:更新时间" json:"updated_at"` // 更新时间
- DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp;comment:删除时间" json:"deleted_at"` // 删除时间
+ 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
+ AlbumName string `gorm:"column:album_name;type:varchar(50);comment:相册名称" json:"album_name"` // 相册名称
+ AlbumType string `gorm:"column:album_type;type:varchar(50);comment:相册类型" json:"album_type"` // 相册类型
+ CoverImage string `gorm:"column:cover_image;type:text;comment:封面图片" json:"cover_image"` // 封面图片
+ CreatedAt time.Time `gorm:"column:created_at;type:timestamp;autoCreateTime;comment:创建时间" json:"created_at"` // 创建时间
+ UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp;autoUpdateTime;comment:更新时间" json:"updated_at"` // 更新时间
+ DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName ScaStorageAlbum's table name
diff --git a/app/auth/model/mysql/model/sca_storage_info.gen.go b/app/auth/model/mysql/model/sca_storage_info.gen.go
index acdadfb..9bb7767 100644
--- a/app/auth/model/mysql/model/sca_storage_info.gen.go
+++ b/app/auth/model/mysql/model/sca_storage_info.gen.go
@@ -18,7 +18,7 @@ type ScaStorageInfo struct {
UserID string `gorm:"column:user_id;type:varchar(50);not null;comment:用户ID" json:"user_id"` // 用户ID
Provider string `gorm:"column:provider;type:varchar(50);comment:供应商" json:"provider"` // 供应商
Bucket string `gorm:"column:bucket;type:varchar(50);comment:存储桶" json:"bucket"` // 存储桶
- Path string `gorm:"column:path;type:varchar(255);comment:路径" json:"path"` // 路径
+ Path string `gorm:"column:path;type:text;comment:路径" json:"path"` // 路径
FileName string `gorm:"column:file_name;type:varchar(100);comment:文件名称" json:"file_name"` // 文件名称
FileSize string `gorm:"column:file_size;type:varchar(50);comment:文件大小" json:"file_size"` // 文件大小
FileType string `gorm:"column:file_type;type:varchar(50);comment:文件类型" json:"file_type"` // 文件类型
diff --git a/app/auth/model/mysql/query/sca_storage_album.gen.go b/app/auth/model/mysql/query/sca_storage_album.gen.go
index 478f824..afc4cc3 100644
--- a/app/auth/model/mysql/query/sca_storage_album.gen.go
+++ b/app/auth/model/mysql/query/sca_storage_album.gen.go
@@ -31,6 +31,7 @@ func newScaStorageAlbum(db *gorm.DB, opts ...gen.DOOption) scaStorageAlbum {
_scaStorageAlbum.UserID = field.NewString(tableName, "user_id")
_scaStorageAlbum.AlbumName = field.NewString(tableName, "album_name")
_scaStorageAlbum.AlbumType = field.NewString(tableName, "album_type")
+ _scaStorageAlbum.CoverImage = field.NewString(tableName, "cover_image")
_scaStorageAlbum.CreatedAt = field.NewTime(tableName, "created_at")
_scaStorageAlbum.UpdatedAt = field.NewTime(tableName, "updated_at")
_scaStorageAlbum.DeletedAt = field.NewField(tableName, "deleted_at")
@@ -43,14 +44,15 @@ func newScaStorageAlbum(db *gorm.DB, opts ...gen.DOOption) scaStorageAlbum {
type scaStorageAlbum struct {
scaStorageAlbumDo
- ALL field.Asterisk
- ID field.Int64 // 主键
- UserID field.String // 用户ID
- AlbumName field.String // 相册名称
- AlbumType field.String // 相册类型
- CreatedAt field.Time // 创建时间
- UpdatedAt field.Time // 更新时间
- DeletedAt field.Field // 删除时间
+ ALL field.Asterisk
+ ID field.Int64 // 主键
+ UserID field.String // 用户ID
+ AlbumName field.String // 相册名称
+ AlbumType field.String // 相册类型
+ CoverImage field.String // 封面图片
+ CreatedAt field.Time // 创建时间
+ UpdatedAt field.Time // 更新时间
+ DeletedAt field.Field // 删除时间
fieldMap map[string]field.Expr
}
@@ -71,6 +73,7 @@ func (s *scaStorageAlbum) updateTableName(table string) *scaStorageAlbum {
s.UserID = field.NewString(table, "user_id")
s.AlbumName = field.NewString(table, "album_name")
s.AlbumType = field.NewString(table, "album_type")
+ s.CoverImage = field.NewString(table, "cover_image")
s.CreatedAt = field.NewTime(table, "created_at")
s.UpdatedAt = field.NewTime(table, "updated_at")
s.DeletedAt = field.NewField(table, "deleted_at")
@@ -90,11 +93,12 @@ func (s *scaStorageAlbum) GetFieldByName(fieldName string) (field.OrderExpr, boo
}
func (s *scaStorageAlbum) fillFieldMap() {
- s.fieldMap = make(map[string]field.Expr, 7)
+ s.fieldMap = make(map[string]field.Expr, 8)
s.fieldMap["id"] = s.ID
s.fieldMap["user_id"] = s.UserID
s.fieldMap["album_name"] = s.AlbumName
s.fieldMap["album_type"] = s.AlbumType
+ s.fieldMap["cover_image"] = s.CoverImage
s.fieldMap["created_at"] = s.CreatedAt
s.fieldMap["updated_at"] = s.UpdatedAt
s.fieldMap["deleted_at"] = s.DeletedAt
diff --git a/common/constant/mongodb.go b/common/constant/mongodb.go
deleted file mode 100644
index 95247dc..0000000
--- a/common/constant/mongodb.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package constant
-
-const (
- COMMENT_IMAGES = "comment_images"
-)
diff --git a/common/constant/bucket_name.go b/common/constant/oss_config.go
similarity index 100%
rename from common/constant/bucket_name.go
rename to common/constant/oss_config.go
diff --git a/common/constant/redis_prefix.go b/common/constant/redis_prefix.go
index ad81c32..4343f32 100644
--- a/common/constant/redis_prefix.go
+++ b/common/constant/redis_prefix.go
@@ -2,11 +2,12 @@ package constant
// 用户相关的redis key
const (
- UserClientPrefix string = "user:client:"
- UserCaptchaPrefix string = "user:captcha:"
- UserTokenPrefix string = "user:token:"
- UserSmsRedisPrefix string = "user:sms:"
- UserQrcodePrefix = "user:qrcode:"
+ UserClientPrefix string = "user:client:"
+ UserCaptchaPrefix string = "user:captcha:"
+ UserTokenPrefix string = "user:token:"
+ UserSmsRedisPrefix string = "user:sms:"
+ UserQrcodePrefix = "user:qrcode:"
+ UserOssConfigPrefix = "user:oss:"
)
// 系统相关的redis key
@@ -18,3 +19,8 @@ const (
FaceSamplePrefix = "face:samples:"
FaceVectorPrefix = "face:vectors:"
)
+
+const (
+ ImageListPrefix = "image:list:"
+ ImageListMetaPrefix = "image:meta:"
+)
diff --git a/common/storage/storage/aliyun_oss.go b/common/storage/storage/aliyun_oss.go
index c9c00a1..e6f0491 100644
--- a/common/storage/storage/aliyun_oss.go
+++ b/common/storage/storage/aliyun_oss.go
@@ -13,6 +13,7 @@ import (
"schisandra-album-cloud-microservices/common/storage/config"
"schisandra-album-cloud-microservices/common/storage/events"
"sync"
+ "time"
)
type AliOSS struct {
@@ -400,5 +401,19 @@ func (a *AliOSS) RenameObject(ctx context.Context, destBucketName, destObjectNam
return -1, fmt.Errorf("failed to delete object, error: %v", err)
}
return deleteResult.StatusCode, nil
-
+}
+
+// PresignedURL 生成预签名URL
+func (a *AliOSS) PresignedURL(ctx context.Context, bucketName, objectKey string, expires time.Duration) (string, error) {
+
+ // 生成预签名URL
+ presignedResult, err := a.client.Presign(ctx, &oss.GetObjectRequest{
+ Bucket: oss.Ptr(bucketName),
+ Key: oss.Ptr(objectKey),
+ }, oss.PresignExpires(expires))
+ if err != nil {
+ return "", fmt.Errorf("failed to generate presigned URL, error: %v", err)
+ }
+
+ return presignedResult.URL, nil
}
diff --git a/common/storage/storage/interface.go b/common/storage/storage/interface.go
index 999dc9d..607f7c8 100644
--- a/common/storage/storage/interface.go
+++ b/common/storage/storage/interface.go
@@ -74,4 +74,5 @@ type Service interface {
ListObjects(ctx context.Context, bucketName string, maxKeys int32) ([]ObjectProperties, error)
DeleteObject(ctx context.Context, bucketName, objectName string) (int, error)
RenameObject(ctx context.Context, destBucketName, destObjectName, srcObjectName, srcBucketName string) (int, error)
+ PresignedURL(ctx context.Context, bucketName, objectKey string, expires time.Duration) (string, error)
}