🚧 under development

This commit is contained in:
2025-02-08 00:46:03 +08:00
parent d2b0d7b42e
commit 7e81a4ff96
32 changed files with 1119 additions and 165 deletions

176
.idea/GOHCache.xml generated
View File

@@ -164,13 +164,6 @@
</set>
</value>
</entry>
<entry key="CommentImages">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/auth/api/internal/types/comment.go" />
</set>
</value>
</entry>
<entry key="CommentLikeRequest">
<value>
<set>
@@ -228,6 +221,20 @@
</set>
</value>
</entry>
<entry key="CreateAlbumLogic">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/auth/api/internal/logic/storage/create_album_logic.go" />
</set>
</value>
</entry>
<entry key="DeleteAlbumLogic">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/auth/api/internal/logic/storage/delete_album_logic.go" />
</set>
</value>
</entry>
<entry key="Direction">
<value>
<set>
@@ -376,6 +383,13 @@
</set>
</value>
</entry>
<entry key="GetAlbumListLogic">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/auth/api/internal/logic/storage/get_album_list_logic.go" />
</set>
</value>
</entry>
<entry key="GetCommentListLogic">
<value>
<set>
@@ -793,6 +807,13 @@
</set>
</value>
</entry>
<entry key="RenameAlbumLogic">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/auth/api/internal/logic/storage/rename_album_logic.go" />
</set>
</value>
</entry>
<entry key="ReplyCommentRequest">
<value>
<set>
@@ -1728,7 +1749,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/api/internal/config/config.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738725465053" />
<option name="lastModified" value="1738750192509" />
<option name="schema">
<list>
<option value="Config" />
@@ -2269,6 +2290,42 @@
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/auth/api/internal/logic/storage/create_album_logic.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738815216096" />
<option name="schema">
<list>
<option value="CreateAlbumLogic" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/auth/api/internal/logic/storage/delete_album_logic.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738819062804" />
<option name="schema">
<list>
<option value="DeleteAlbumLogic" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/auth/api/internal/logic/storage/get_album_list_logic.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738814756828" />
<option name="schema">
<list>
<option value="GetAlbumListLogic" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/auth/api/internal/logic/storage/get_face_sample_library_list_logic.go">
<value>
<ScannedPath>
@@ -2305,6 +2362,18 @@
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/auth/api/internal/logic/storage/rename_album_logic.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738818831989" />
<option name="schema">
<list>
<option value="RenameAlbumLogic" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/auth/api/internal/logic/storage/set_storage_config_logic.go">
<value>
<ScannedPath>
@@ -2578,20 +2647,6 @@
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/auth/model/mongodb/collection.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738743805056" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/auth/model/mongodb/mongodb.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738743883537" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/generate/generate.go">
<value>
<ScannedPath>
@@ -2602,7 +2657,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_auth_menu.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437433" />
<option name="lastModified" value="1738745822582" />
<option name="schema">
<list>
<option value="ScaAuthMenu" />
@@ -2614,7 +2669,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_auth_permission_rule.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437915" />
<option name="lastModified" value="1738745822877" />
<option name="schema">
<list>
<option value="ScaAuthPermissionRule" />
@@ -2626,7 +2681,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_auth_role.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437563" />
<option name="lastModified" value="1738745822478" />
<option name="schema">
<list>
<option value="ScaAuthRole" />
@@ -2638,7 +2693,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_auth_user.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437939" />
<option name="lastModified" value="1738745822914" />
<option name="schema">
<list>
<option value="ScaAuthUser" />
@@ -2650,7 +2705,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_auth_user_device.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437852" />
<option name="lastModified" value="1738745822455" />
<option name="schema">
<list>
<option value="ScaAuthUserDevice" />
@@ -2662,7 +2717,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_auth_user_social.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437510" />
<option name="lastModified" value="1738745822509" />
<option name="schema">
<list>
<option value="ScaAuthUserSocial" />
@@ -2674,7 +2729,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_comment_likes.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437573" />
<option name="lastModified" value="1738745822915" />
<option name="schema">
<list>
<option value="ScaCommentLike" />
@@ -2686,7 +2741,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_comment_reply.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724443542" />
<option name="lastModified" value="1738745828028" />
<option name="schema">
<list>
<option value="ScaCommentReply" />
@@ -2698,7 +2753,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_message_report.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437887" />
<option name="lastModified" value="1738745822535" />
<option name="schema">
<list>
<option value="ScaMessageReport" />
@@ -2710,7 +2765,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_storage_album.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437572" />
<option name="lastModified" value="1738745822867" />
<option name="schema">
<list>
<option value="ScaStorageAlbum" />
@@ -2722,7 +2777,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_storage_config.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437580" />
<option name="lastModified" value="1738745822467" />
<option name="schema">
<list>
<option value="ScaStorageConfig" />
@@ -2734,7 +2789,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_storage_info.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437559" />
<option name="lastModified" value="1738745822631" />
<option name="schema">
<list>
<option value="ScaStorageInfo" />
@@ -2746,7 +2801,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_storage_tag.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437473" />
<option name="lastModified" value="1738745822539" />
<option name="schema">
<list>
<option value="ScaStorageTag" />
@@ -2758,7 +2813,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_storage_tag_info.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437886" />
<option name="lastModified" value="1738745822542" />
<option name="schema">
<list>
<option value="ScaStorageTagInfo" />
@@ -2770,7 +2825,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_user_follows.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437444" />
<option name="lastModified" value="1738745822643" />
<option name="schema">
<list>
<option value="ScaUserFollow" />
@@ -2782,7 +2837,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_user_level.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437595" />
<option name="lastModified" value="1738745822575" />
<option name="schema">
<list>
<option value="ScaUserLevel" />
@@ -2794,7 +2849,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/model/sca_user_message.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724437640" />
<option name="lastModified" value="1738745822866" />
<option name="schema">
<list>
<option value="ScaUserMessage" />
@@ -2813,7 +2868,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445814" />
<option name="lastModified" value="1738745830286" />
<option name="schema">
<list>
<option value="Query" />
@@ -2827,7 +2882,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_auth_menu.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445474" />
<option name="lastModified" value="1738745829664" />
<option name="schema">
<list>
<option value="scaAuthMenu" />
@@ -2840,7 +2895,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_auth_permission_rule.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445504" />
<option name="lastModified" value="1738745829577" />
<option name="schema">
<list>
<option value="scaAuthPermissionRule" />
@@ -2853,7 +2908,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_auth_role.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445505" />
<option name="lastModified" value="1738745829662" />
<option name="schema">
<list>
<option value="scaAuthRole" />
@@ -2866,7 +2921,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_auth_user.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445138" />
<option name="lastModified" value="1738745829769" />
<option name="schema">
<list>
<option value="scaAuthUser" />
@@ -2879,7 +2934,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_auth_user_device.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445105" />
<option name="lastModified" value="1738745829808" />
<option name="schema">
<list>
<option value="scaAuthUserDevice" />
@@ -2892,7 +2947,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_auth_user_social.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445196" />
<option name="lastModified" value="1738745829959" />
<option name="schema">
<list>
<option value="scaAuthUserSocial" />
@@ -2905,7 +2960,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_comment_likes.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445107" />
<option name="lastModified" value="1738745830000" />
<option name="schema">
<list>
<option value="scaCommentLike" />
@@ -2918,7 +2973,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_comment_reply.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445141" />
<option name="lastModified" value="1738745829808" />
<option name="schema">
<list>
<option value="scaCommentReply" />
@@ -2931,7 +2986,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_message_report.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445529" />
<option name="lastModified" value="1738745830008" />
<option name="schema">
<list>
<option value="scaMessageReport" />
@@ -2944,7 +2999,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_storage_album.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445062" />
<option name="lastModified" value="1738745829756" />
<option name="schema">
<list>
<option value="scaStorageAlbum" />
@@ -2957,7 +3012,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_storage_config.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445517" />
<option name="lastModified" value="1738745829593" />
<option name="schema">
<list>
<option value="scaStorageConfig" />
@@ -2970,7 +3025,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_storage_info.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445221" />
<option name="lastModified" value="1738745830019" />
<option name="schema">
<list>
<option value="scaStorageInfo" />
@@ -2983,7 +3038,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_storage_tag.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445147" />
<option name="lastModified" value="1738745829616" />
<option name="schema">
<list>
<option value="scaStorageTag" />
@@ -2996,7 +3051,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_storage_tag_info.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445224" />
<option name="lastModified" value="1738745829615" />
<option name="schema">
<list>
<option value="scaStorageTagInfo" />
@@ -3009,7 +3064,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_user_follows.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445066" />
<option name="lastModified" value="1738745829988" />
<option name="schema">
<list>
<option value="scaUserFollow" />
@@ -3022,7 +3077,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_user_level.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445196" />
<option name="lastModified" value="1738745829768" />
<option name="schema">
<list>
<option value="scaUserLevel" />
@@ -3035,7 +3090,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/model/mysql/query/sca_user_message.gen.go">
<value>
<ScannedPath>
<option name="lastModified" value="1738724445059" />
<option name="lastModified" value="1738745829555" />
<option name="schema">
<list>
<option value="scaUserMessage" />
@@ -3822,7 +3877,6 @@
<entry key="code_msg" value="CodeMsg" />
<entry key="comment_content" value="CommentContent" />
<entry key="comment_dis_like_request" value="CommentDisLikeRequest" />
<entry key="comment_images" value="CommentImages" />
<entry key="comment_like_request" value="CommentLikeRequest" />
<entry key="comment_list_page_response" value="CommentListPageResponse" />
<entry key="comment_list_query_result" value="CommentListQueryResult" />
@@ -3831,8 +3885,10 @@
<entry key="comment_response" value="CommentResponse" />
<entry key="complete_multipart_upload_result" value="CompleteMultipartUploadResult" />
<entry key="config" value="Config" />
<entry key="create_album_logic" value="CreateAlbumLogic" />
<entry key="default_ai_service" value="defaultAiService" />
<entry key="default_dispatcher" value="defaultDispatcher" />
<entry key="delete_album_logic" value="DeleteAlbumLogic" />
<entry key="direction" value="Direction" />
<entry key="dislike_comment_logic" value="DislikeCommentLogic" />
<entry key="district" value="District" />
@@ -3854,6 +3910,7 @@
<entry key="generate_slide_basic_captcha_logic" value="GenerateSlideBasicCaptchaLogic" />
<entry key="geo" value="Geo" />
<entry key="geo_response" value="GeoResponse" />
<entry key="get_album_list_logic" value="GetAlbumListLogic" />
<entry key="get_comment_list_logic" value="GetCommentListLogic" />
<entry key="get_face_sample_library_list_logic" value="GetFaceSampleLibraryListLogic" />
<entry key="get_gitee_oauth_url_logic" value="GetGiteeOauthUrlLogic" />
@@ -3914,6 +3971,7 @@
<entry key="refresh_jwt_payload" value="RefreshJWTPayload" />
<entry key="refresh_token_logic" value="RefreshTokenLogic" />
<entry key="refresh_token_response" value="RefreshTokenResponse" />
<entry key="rename_album_logic" value="RenameAlbumLogic" />
<entry key="reply_comment_request" value="ReplyCommentRequest" />
<entry key="reply_list_query_result" value="ReplyListQueryResult" />
<entry key="reply_list_request" value="ReplyListRequest" />
@@ -3991,6 +4049,6 @@
<entry key="x" value="x" />
</map>
</option>
<option name="lastTimeChecked" value="1738720848734" />
<option name="lastTimeChecked" value="1738807721203" />
</component>
</project>

View File

@@ -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)
}

View File

@@ -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:
# 访问密钥

View File

@@ -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

View File

@@ -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)
}
}
}

View File

@@ -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",

View File

@@ -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 {

View 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 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)
}
}
}

View 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 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)
}
}
}

View 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 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)
}
}
}

View 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 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)
}
}
}

View 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 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)
}
}
}

View 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 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)
}
}
}

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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
}

View 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 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
}

View File

@@ -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
}

View 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 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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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"`

View File

@@ -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"`

View File

@@ -18,6 +18,7 @@ type ScaStorageAlbum struct {
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"` // 删除时间

View File

@@ -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"` // 文件类型

View File

@@ -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")
@@ -48,6 +49,7 @@ type scaStorageAlbum struct {
UserID field.String // 用户ID
AlbumName field.String // 相册名称
AlbumType field.String // 相册类型
CoverImage field.String // 封面图片
CreatedAt field.Time // 创建时间
UpdatedAt field.Time // 更新时间
DeletedAt field.Field // 删除时间
@@ -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

View File

@@ -1,5 +0,0 @@
package constant
const (
COMMENT_IMAGES = "comment_images"
)

View File

@@ -7,6 +7,7 @@ const (
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:"
)

View File

@@ -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
}

View File

@@ -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)
}