add apis

This commit is contained in:
2025-03-06 00:08:16 +08:00
parent d8d98eb31c
commit 7b2b6cc76b
15 changed files with 607 additions and 42 deletions

View File

@@ -40,7 +40,7 @@ type (
AccessToken string `json:"access_token"`
ExpireAt int64 `json:"expire_at"`
UID string `json:"uid"`
Username string `json:"username,omitempty"`
Username string `json:"username,optional"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
Status int64 `json:"status"`
@@ -316,15 +316,15 @@ type (
CommentContent {
NickName string `json:"nickname"`
Avatar string `json:"avatar"`
Level int64 `json:"level,omitempty" default:"0"`
Level int64 `json:"level,optional" default:"0"`
Id int64 `json:"id"`
UserId string `json:"user_id"`
TopicId string `json:"topic_id"`
Content string `json:"content"`
ReplyTo int64 `json:"reply_to,omitempty"`
ReplyId int64 `json:"reply_id,omitempty"`
ReplyUser string `json:"reply_user,omitempty"`
ReplyNickname string `json:"reply_nickname,omitempty"`
ReplyTo int64 `json:"reply_to,optional"`
ReplyId int64 `json:"reply_id,optional"`
ReplyUser string `json:"reply_user,optional"`
ReplyNickname string `json:"reply_nickname,optional"`
IsAuthor int64 `json:"is_author"`
Likes int64 `json:"likes"`
ReplyCount int64 `json:"reply_count"`
@@ -333,7 +333,7 @@ type (
Browser string `json:"browser"`
OperatingSystem string `json:"operating_system"`
IsLiked bool `json:"is_liked" default:"false"`
Images string `json:"images,omitempty"`
Images string `json:"images,optional"`
}
// CommentListPageResponse 评论返回值
CommentListPageResponse {
@@ -353,9 +353,9 @@ type (
Browser string `json:"browser"`
OperatingSystem string `json:"operating_system"`
CreatedTime string `json:"created_time"`
ReplyId int64 `json:"reply_id,omitempty"`
ReplyUser string `json:"reply_user,omitempty"`
ReplyTo int64 `json:"reply_to,omitempty"`
ReplyId int64 `json:"reply_id,optional"`
ReplyUser string `json:"reply_user,optional"`
ReplyTo int64 `json:"reply_to,optional"`
}
)
@@ -482,7 +482,7 @@ type (
}
// 相册列表请求参数
AlbumListRequest {
Type int64 `json:"type,omitempty"`
Type int64 `json:"type,optional"`
Sort bool `json:"sort"`
}
// 相册列表响应参数
@@ -649,8 +649,8 @@ type (
ShareAlbumRequest {
ID int64 `json:"id"`
ExpireDate string `json:"expire_date"`
AccessLimit int64 `json:"access_limit,omitempty"`
AccessPassword string `json:"access_password,omitempty"`
AccessLimit int64 `json:"access_limit,optional"`
AccessPassword string `json:"access_password,optional"`
Provider string `json:"provider"`
Bucket string `json:"bucket"`
}
@@ -705,6 +705,28 @@ type (
Provider string `json:"provider"`
Bucket string `json:"bucket"`
}
HeatmapMeta {
Date string `json:"date"`
Count int64 `json:"count"`
}
UserUploadInfoResponse {
ImageCount int64 `json:"image_count"`
TodayUploadCount int64 `json:"today_upload_count"`
ShareCount int64 `json:"share_count"`
TodayShareCount int64 `json:"today_share_count"`
FileSizeCount int64 `json:"file_size_count"`
TodayFileSizeCount int64 `json:"today_file_size_count"`
Heatmap []HeatmapMeta `json:"heatmap"`
}
ShareRecentMeta {
Date string `json:"date"`
VisitCount int64 `json:"visit_count"`
VisitorCount int64 `json:"visitor_count"`
PublishCount int64 `json:"publish_count"`
}
ShareRecentInfoResponse {
Records []ShareRecentMeta `json:"records"`
}
)
// 文件上传
@@ -835,6 +857,14 @@ service auth {
// 删除存储配置
@handler deleteStorageConfig
post /config/delete (DeleteStorageConfigRequest) returns (string)
// 获取用户上传统计信息
@handler getUserUploadInfo
post /user/upload/info returns (UserUploadInfoResponse)
// 获取分享最近的数据统计
@handler getShareRecentInfo
post /share/recent/info returns (ShareRecentInfoResponse)
}
type (
@@ -848,15 +878,15 @@ type (
ThumbSize int64 `json:"thumb_size"`
}
ShareImageRequest {
Title string `json:"title,omitempty"`
Title string `json:"title,optional"`
ExpireDate string `json:"expire_date"`
AccessLimit int64 `json:"access_limit,omitempty"`
AccessPassword string `json:"access_password,omitempty"`
AccessLimit int64 `json:"access_limit,optional"`
AccessPassword string `json:"access_password,optional"`
Images []ShareImageMeta `json:"images"`
}
QueryShareImageRequest {
InviteCode string `json:"invite_code"`
AccessPassword string `json:"access_password,omitempty"`
AccessPassword string `json:"access_password,optional"`
}
QueryShareImageResponse {
Records []AllImageDetail `json:"records"`
@@ -880,7 +910,7 @@ type (
}
QueryShareInfoRequest {
InviteCode string `json:"invite_code"`
AccessPassword string `json:"access_password,omitempty"`
AccessPassword string `json:"access_password,optional"`
}
ShareInfoResponse {
ID int64 `json:"id"`
@@ -951,3 +981,33 @@ service auth {
post /record/delete (DeleteShareRecordRequest) returns (string)
}
type (
UserSecuritySettingResponse {
bindPhone bool `json:"bind_phone,default=false"`
bindEmail bool `json:"bind_email,default=falsel"`
bindWechat bool `json:"bind_wechat,default=false"`
bindQQ bool `json:"bind_qq,default=false"`
bindGitHub bool `json:"bind_github,default=false"`
bindGitee bool `json:"bind_gitee,default=false"`
setPassword bool `json:"set_password,default=false"`
}
)
// 分享服务
@server (
group: auth // 微服务分组
prefix: /api/auth/user // 微服务前缀
timeout: 10s // 超时时间
maxBytes: 104857600 // 最大请求大小
signature: false // 是否开启签名验证
middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware,NonceMiddleware // 注册中间件
MaxConns: true // 是否开启最大连接数限制
Recover: true // 是否开启自动恢复
jwt: Auth // 是否开启jwt验证
)
service auth {
// 判断用户安全设置
@handler checkUserSecuritySetting
post /check/security/setting returns (UserSecuritySettingResponse)
}

View File

@@ -0,0 +1,21 @@
package auth
import (
"net/http"
"schisandra-album-cloud-microservices/app/auth/api/internal/logic/auth"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/common/xhttp"
)
func CheckUserSecuritySettingHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := auth.NewCheckUserSecuritySettingLogic(r.Context(), svcCtx)
resp, err := l.CheckUserSecuritySetting()
if err != nil {
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
} else {
xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
}
}
}

View File

@@ -7,6 +7,7 @@ import (
"net/http"
"time"
auth "schisandra-album-cloud-microservices/app/auth/api/internal/handler/auth"
captcha "schisandra-album-cloud-microservices/app/auth/api/internal/handler/captcha"
client "schisandra-album-cloud-microservices/app/auth/api/internal/handler/client"
comment "schisandra-album-cloud-microservices/app/auth/api/internal/handler/comment"
@@ -24,6 +25,23 @@ import (
)
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware, serverCtx.NonceMiddleware},
[]rest.Route{
{
Method: http.MethodPost,
Path: "/check/security/setting",
Handler: auth.CheckUserSecuritySettingHandler(serverCtx),
},
}...,
),
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
rest.WithPrefix("/api/auth/user"),
rest.WithTimeout(10000*time.Millisecond),
rest.WithMaxBytes(104857600),
)
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.NonceMiddleware},
@@ -387,6 +405,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/image/url/single",
Handler: storage.GetImageUrlHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/share/recent/info",
Handler: storage.GetShareRecentInfoHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/uploads",
@@ -402,6 +425,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/user/storage/list",
Handler: storage.ListUserStorageHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/user/upload/info",
Handler: storage.GetUserUploadInfoHandler(serverCtx),
},
}...,
),
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),

View File

@@ -0,0 +1,21 @@
package storage
import (
"net/http"
"schisandra-album-cloud-microservices/app/auth/api/internal/logic/storage"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/common/xhttp"
)
func GetShareRecentInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := storage.NewGetShareRecentInfoLogic(r.Context(), svcCtx)
resp, err := l.GetShareRecentInfo()
if err != nil {
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
} else {
xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
}
}
}

View File

@@ -0,0 +1,21 @@
package storage
import (
"net/http"
"schisandra-album-cloud-microservices/app/auth/api/internal/logic/storage"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/common/xhttp"
)
func GetUserUploadInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := storage.NewGetUserUploadInfoLogic(r.Context(), svcCtx)
resp, err := l.GetUserUploadInfo()
if err != nil {
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
} else {
xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
}
}
}

View File

@@ -0,0 +1,64 @@
package auth
import (
"context"
"errors"
"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"
"github.com/zeromicro/go-zero/core/logx"
)
type CheckUserSecuritySettingLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewCheckUserSecuritySettingLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CheckUserSecuritySettingLogic {
return &CheckUserSecuritySettingLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *CheckUserSecuritySettingLogic) CheckUserSecuritySetting() (resp *types.UserSecuritySettingResponse, err error) {
uid, ok := l.ctx.Value("user_id").(string)
if !ok {
return nil, errors.New("user_id not found")
}
authUser := l.svcCtx.DB.ScaAuthUser
userSocial := l.svcCtx.DB.ScaAuthUserSocial
var user model.ScaAuthUser
err = authUser.Where(authUser.UID.Eq(uid)).Scan(&user)
if err != nil {
return nil, err
}
// 查询用户社交信息
var socials []model.ScaAuthUserSocial
err = userSocial.Where(userSocial.UserID.Eq(uid)).Scan(&socials)
if err != nil {
return nil, err
}
resp = &types.UserSecuritySettingResponse{
SetPassword: user.Password != "",
BindEmail: user.Email != "",
BindPhone: user.Phone != "",
}
// 遍历社交信息以设置绑定状态
for _, social := range socials {
switch social.Source {
case "wechat":
resp.BindWechat = true
case "qq":
resp.BindQQ = true
case "gitee":
resp.BindGitee = true
case "github":
resp.BindGitHub = true
}
}
return resp, nil
}

View File

@@ -163,7 +163,7 @@ func (l *UploadShareImageLogic) uploadImageAndRecord(tx *query.QueryTx, uid stri
UserID: uid,
Path: originObjectKey,
FileName: img.FileName,
FileSize: strconv.Itoa(size),
FileSize: int64(size),
FileType: img.FileType,
Width: float64(width),
Height: float64(height),

View File

@@ -0,0 +1,112 @@
package storage
import (
"context"
"errors"
"time"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetShareRecentInfoLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetShareRecentInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetShareRecentInfoLogic {
return &GetShareRecentInfoLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetShareRecentInfoLogic) GetShareRecentInfo() (resp *types.ShareRecentInfoResponse, err error) {
uid, ok := l.ctx.Value("user_id").(string)
if !ok {
return nil, errors.New("user_id not found")
}
// 生成最近7天的日期列表包含今天
now := time.Now().Truncate(24 * time.Hour)
dates := make([]string, 7)
for i := 0; i < 7; i++ {
date := now.AddDate(0, 0, -i).Format("2006-01-02")
dates[6-i] = date // 保证日期顺序从旧到新
}
// 计算查询时间范围
startDate := now.AddDate(0, 0, -6)
endDate := now
// 查询每日发布次数
var publishStats []struct {
Date string
Count int64
}
storageShare := l.svcCtx.DB.ScaStorageShare
err = storageShare.
Select(storageShare.CreatedAt.Date().As("date"),
storageShare.ID.Count().As("count")).
Where(storageShare.UserID.Eq(uid)).
Where(storageShare.CreatedAt.Between(startDate, endDate)).
Group(storageShare.CreatedAt.Date()).
Scan(&publishStats)
if err != nil {
return nil, err
}
// 查询每日访问数据
var visitStats []struct {
Date string
VisitCount int64
VisitorCount int64
}
shareVisit := l.svcCtx.DB.ScaStorageShareVisit
err = shareVisit.Select(
shareVisit.CreatedAt.Date().As("date"),
shareVisit.ID.Count().As("visit_count"),
shareVisit.UserID.Distinct().Count().As("visitor_count")).
Join(storageShare, shareVisit.ShareID.EqCol(storageShare.ID)).
Where(storageShare.UserID.Eq(uid),
shareVisit.CreatedAt.Between(startDate, endDate)).
Group(shareVisit.CreatedAt.Date()).
Scan(&visitStats)
if err != nil {
return nil, err
}
// 初始化结果映射
resultMap := make(map[string]*types.ShareRecentMeta)
for _, date := range dates {
resultMap[date] = &types.ShareRecentMeta{
Date: date,
VisitCount: 0,
VisitorCount: 0,
PublishCount: 0,
}
}
// 填充发布数据
for _, stat := range publishStats {
if meta, exists := resultMap[stat.Date]; exists {
meta.PublishCount = stat.Count
}
}
// 填充访问数据
for _, stat := range visitStats {
if meta, exists := resultMap[stat.Date]; exists {
meta.VisitCount = stat.VisitCount
meta.VisitorCount = stat.VisitorCount
}
}
// 构建有序结果
records := make([]types.ShareRecentMeta, 0, 7)
for _, date := range dates {
records = append(records, *resultMap[date])
}
return &types.ShareRecentInfoResponse{Records: records}, nil
}

View File

@@ -0,0 +1,96 @@
package storage
import (
"context"
"errors"
"time"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetUserUploadInfoLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetUserUploadInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserUploadInfoLogic {
return &GetUserUploadInfoLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetUserUploadInfoLogic) GetUserUploadInfo() (resp *types.UserUploadInfoResponse, err error) {
uid, ok := l.ctx.Value("user_id").(string)
if !ok {
return nil, errors.New("user_id not found")
}
// 图片数
storageInfo := l.svcCtx.DB.ScaStorageInfo
var imageResult struct {
ImageCount int64 `json:"image_count"`
FileSizeCount int64 `json:"file_size_count"`
}
err = storageInfo.Select(storageInfo.ID.Count().As("image_count"),
storageInfo.FileSize.Sum().As("file_size_count")).Where(storageInfo.UserID.Eq(uid)).Scan(&imageResult)
if err != nil {
return nil, err
}
// 分享数
storageShare := l.svcCtx.DB.ScaStorageShare
var shareCount int64
err = storageShare.Select(storageShare.ID.Count().As("share_count")).Where(storageShare.UserID.Eq(uid)).Scan(&shareCount)
if err != nil {
return nil, err
}
// 今日上传数
var todayResult struct {
TodayUploadCount int64 `json:"today_upload_count"`
TodayFileSizeCount int64 `json:"today_file_size_count"`
}
err = storageInfo.Select(
storageInfo.ID.Count().As("today_upload_count"),
storageInfo.FileSize.Sum().As("today_file_size_count")).Where(storageInfo.UserID.Eq(uid),
storageInfo.CreatedAt.Gte(time.Now().Truncate(24*time.Hour))).Scan(&todayResult)
if err != nil {
return nil, err
}
// 今日分享数
var todayShareCount int64
err = storageShare.Select(storageShare.ID.Count().As("today_share_count")).Where(storageShare.UserID.Eq(uid),
storageShare.CreatedAt.Gte(time.Now().Truncate(24*time.Hour))).Scan(&todayShareCount)
if err != nil {
return nil, err
}
// 热力图
heatmap := make([]types.HeatmapMeta, 0)
err = storageInfo.Select(
storageInfo.CreatedAt.Date().As("date"),
storageInfo.ID.Count().As("count"),
).
Where(storageInfo.UserID.Eq(uid)).
Group(storageInfo.CreatedAt.Date()).
Order(storageInfo.CreatedAt.Date().Desc()).
Scan(&heatmap)
if err != nil {
return nil, err
}
resp = &types.UserUploadInfoResponse{
ImageCount: imageResult.ImageCount,
TodayUploadCount: todayResult.TodayUploadCount,
ShareCount: shareCount,
TodayShareCount: todayShareCount,
FileSizeCount: imageResult.FileSizeCount,
TodayFileSizeCount: todayResult.TodayFileSizeCount,
Heatmap: heatmap,
}
return resp, nil
}

View File

@@ -280,7 +280,7 @@ func (c *NsqImageProcessConsumer) saveFileInfoToDB(uid, bucket, provider string,
Provider: provider,
Bucket: bucket,
FileName: fileName,
FileSize: strconv.FormatInt(fileSize, 10),
FileSize: fileSize,
FileType: result.FileType,
Path: filePath,
FaceID: faceId,

View File

@@ -50,7 +50,7 @@ type AlbumDetailListResponse struct {
}
type AlbumListRequest struct {
Type int64 `json:"type,omitempty"`
Type int64 `json:"type,optional"`
Sort bool `json:"sort"`
}
@@ -98,15 +98,15 @@ type BucketCapacityResponse struct {
type CommentContent struct {
NickName string `json:"nickname"`
Avatar string `json:"avatar"`
Level int64 `json:"level,omitempty" default:"0"`
Level int64 `json:"level,optional" default:"0"`
Id int64 `json:"id"`
UserId string `json:"user_id"`
TopicId string `json:"topic_id"`
Content string `json:"content"`
ReplyTo int64 `json:"reply_to,omitempty"`
ReplyId int64 `json:"reply_id,omitempty"`
ReplyUser string `json:"reply_user,omitempty"`
ReplyNickname string `json:"reply_nickname,omitempty"`
ReplyTo int64 `json:"reply_to,optional"`
ReplyId int64 `json:"reply_id,optional"`
ReplyUser string `json:"reply_user,optional"`
ReplyNickname string `json:"reply_nickname,optional"`
IsAuthor int64 `json:"is_author"`
Likes int64 `json:"likes"`
ReplyCount int64 `json:"reply_count"`
@@ -115,7 +115,7 @@ type CommentContent struct {
Browser string `json:"browser"`
OperatingSystem string `json:"operating_system"`
IsLiked bool `json:"is_liked" default:"false"`
Images string `json:"images,omitempty"`
Images string `json:"images,optional"`
}
type CommentDisLikeRequest struct {
@@ -161,9 +161,9 @@ type CommentResponse struct {
Browser string `json:"browser"`
OperatingSystem string `json:"operating_system"`
CreatedTime string `json:"created_time"`
ReplyId int64 `json:"reply_id,omitempty"`
ReplyUser string `json:"reply_user,omitempty"`
ReplyTo int64 `json:"reply_to,omitempty"`
ReplyId int64 `json:"reply_id,optional"`
ReplyUser string `json:"reply_user,optional"`
ReplyTo int64 `json:"reply_to,optional"`
}
type DeleteImageRequest struct {
@@ -222,6 +222,11 @@ type FaceSampleLibraryListResponse struct {
Faces []FaceSampleLibrary `json:"faces"`
}
type HeatmapMeta struct {
Date string `json:"date"`
Count int64 `json:"count"`
}
type ImageMeta struct {
ID int64 `json:"id"`
FileName string `json:"file_name"`
@@ -267,7 +272,7 @@ type LoginResponse struct {
AccessToken string `json:"access_token"`
ExpireAt int64 `json:"expire_at"`
UID string `json:"uid"`
Username string `json:"username,omitempty"`
Username string `json:"username,optional"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
Status int64 `json:"status"`
@@ -312,7 +317,7 @@ type QueryDeleteRecordRequest struct {
type QueryShareImageRequest struct {
InviteCode string `json:"invite_code"`
AccessPassword string `json:"access_password,omitempty"`
AccessPassword string `json:"access_password,optional"`
}
type QueryShareImageResponse struct {
@@ -321,7 +326,7 @@ type QueryShareImageResponse struct {
type QueryShareInfoRequest struct {
InviteCode string `json:"invite_code"`
AccessPassword string `json:"access_password,omitempty"`
AccessPassword string `json:"access_password,optional"`
}
type RecentListRequest struct {
@@ -403,8 +408,8 @@ type SearchImageResponse struct {
type ShareAlbumRequest struct {
ID int64 `json:"id"`
ExpireDate string `json:"expire_date"`
AccessLimit int64 `json:"access_limit,omitempty"`
AccessPassword string `json:"access_password,omitempty"`
AccessLimit int64 `json:"access_limit,optional"`
AccessPassword string `json:"access_password,optional"`
Provider string `json:"provider"`
Bucket string `json:"bucket"`
}
@@ -420,10 +425,10 @@ type ShareImageMeta struct {
}
type ShareImageRequest struct {
Title string `json:"title,omitempty"`
Title string `json:"title,optional"`
ExpireDate string `json:"expire_date"`
AccessLimit int64 `json:"access_limit,omitempty"`
AccessPassword string `json:"access_password,omitempty"`
AccessLimit int64 `json:"access_limit,optional"`
AccessPassword string `json:"access_password,optional"`
Images []ShareImageMeta `json:"images"`
}
@@ -461,6 +466,17 @@ type SharePhoneUploadRequest struct {
UserId string `json:"user_id"`
}
type ShareRecentInfoResponse struct {
Records []ShareRecentMeta `json:"records"`
}
type ShareRecentMeta struct {
Date string `json:"date"`
VisitCount int64 `json:"visit_count"`
VisitorCount int64 `json:"visitor_count"`
PublishCount int64 `json:"publish_count"`
}
type ShareRecord struct {
ID int64 `json:"id"`
CoverImage string `json:"cover_image"`
@@ -576,6 +592,26 @@ type UploadRequest struct {
UserId string `json:"user_id"`
}
type UserSecuritySettingResponse struct {
BindPhone bool `json:"bind_phone,default=false"`
BindEmail bool `json:"bind_email,default=falsel"`
BindWechat bool `json:"bind_wechat,default=false"`
BindQQ bool `json:"bind_qq,default=false"`
BindGitHub bool `json:"bind_github,default=false"`
BindGitee bool `json:"bind_gitee,default=false"`
SetPassword bool `json:"set_password,default=false"`
}
type UserUploadInfoResponse struct {
ImageCount int64 `json:"image_count"`
TodayUploadCount int64 `json:"today_upload_count"`
ShareCount int64 `json:"share_count"`
TodayShareCount int64 `json:"today_share_count"`
FileSizeCount int64 `json:"file_size_count"`
TodayFileSizeCount int64 `json:"today_file_size_count"`
Heatmap []HeatmapMeta `json:"heatmap"`
}
type WechatOffiaccountLoginRequest struct {
Openid string `json:"openid"`
ClientId string `json:"client_id"`

View File

@@ -20,7 +20,7 @@ type ScaStorageInfo struct {
Bucket string `gorm:"column:bucket;type:varchar(50);comment:存储桶" json:"bucket"` // 存储桶
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"` // 文件大小
FileSize int64 `gorm:"column:file_size;type:bigint(20);comment:文件大小" json:"file_size"` // 文件大小
FileType string `gorm:"column:file_type;type:varchar(50);comment:文件类型" json:"file_type"` // 文件类型
Width float64 `gorm:"column:width;type:double;comment:宽" json:"width"` // 宽
Height float64 `gorm:"column:height;type:double;comment:高" json:"height"` // 高

View File

@@ -33,7 +33,7 @@ func newScaStorageInfo(db *gorm.DB, opts ...gen.DOOption) scaStorageInfo {
_scaStorageInfo.Bucket = field.NewString(tableName, "bucket")
_scaStorageInfo.Path = field.NewString(tableName, "path")
_scaStorageInfo.FileName = field.NewString(tableName, "file_name")
_scaStorageInfo.FileSize = field.NewString(tableName, "file_size")
_scaStorageInfo.FileSize = field.NewInt64(tableName, "file_size")
_scaStorageInfo.FileType = field.NewString(tableName, "file_type")
_scaStorageInfo.Width = field.NewFloat64(tableName, "width")
_scaStorageInfo.Height = field.NewFloat64(tableName, "height")
@@ -62,7 +62,7 @@ type scaStorageInfo struct {
Bucket field.String // 存储桶
Path field.String // 路径
FileName field.String // 文件名称
FileSize field.String // 文件大小
FileSize field.Int64 // 文件大小
FileType field.String // 文件类型
Width field.Float64 // 宽
Height field.Float64 // 高
@@ -96,7 +96,7 @@ func (s *scaStorageInfo) updateTableName(table string) *scaStorageInfo {
s.Bucket = field.NewString(table, "bucket")
s.Path = field.NewString(table, "path")
s.FileName = field.NewString(table, "file_name")
s.FileSize = field.NewString(table, "file_size")
s.FileSize = field.NewInt64(table, "file_size")
s.FileType = field.NewString(table, "file_type")
s.Width = field.NewFloat64(table, "width")
s.Height = field.NewFloat64(table, "height")

View File

@@ -0,0 +1,106 @@
package main
import (
"image"
"image/draw"
"image/png"
"log"
"os"
"testing"
)
func TestImgEncrypt(t *testing.T) {
// 1. 读取并强制转换为RGBA
inputFile, err := os.Open("E:\\Go_WorkSpace\\schisandra-album-cloud-microservices\\common\\img_encrypt\\input.png")
if err != nil {
log.Fatal("打开文件失败:", err)
}
defer inputFile.Close()
srcImg, err := png.Decode(inputFile)
if err != nil {
log.Fatal("解码失败:", err)
}
bounds := srcImg.Bounds()
rgba := image.NewRGBA(bounds)
draw.Draw(rgba, bounds, srcImg, bounds.Min, draw.Src)
// 2. 安全加密(处理有效像素区)
key := []byte{0x1F, 0x3A, 0x7B, 0x9C} // 示例密钥推荐长度4/8/16
secureXor(rgba, key)
// 3. 保存加密图像(禁用压缩)
outputFile, err := os.Create("encrypted.png")
if err != nil {
log.Fatal("创建文件失败:", err)
}
defer outputFile.Close()
encoder := png.Encoder{CompressionLevel: png.NoCompression}
if err := encoder.Encode(outputFile, rgba); err != nil {
log.Fatal("保存失败:", err)
}
}
func TestImgDecrypt(t *testing.T) {
// 1. 读取加密图像
inputFile, err := os.Open("E:\\Go_WorkSpace\\schisandra-album-cloud-microservices\\common\\img_encrypt\\encrypted.png")
if err != nil {
log.Fatal("打开加密文件失败:", err)
}
defer inputFile.Close()
encImg, err := png.Decode(inputFile)
if err != nil {
log.Fatal("解码失败:", err)
}
// 2. 转换为RGBA
bounds := encImg.Bounds()
rgba := image.NewRGBA(bounds)
draw.Draw(rgba, bounds, encImg, bounds.Min, draw.Src)
// 3. 解密(使用相同密钥)
key := []byte{0x1F, 0x3A, 0x7B, 0x9C} // 必须与加密一致
secureXor(rgba, key)
// 4. 保存解密结果
outputFile, err := os.Create("decrypted.png")
if err != nil {
log.Fatal("创建解密文件失败:", err)
}
defer outputFile.Close()
encoder := png.Encoder{CompressionLevel: png.NoCompression}
if err := encoder.Encode(outputFile, rgba); err != nil {
log.Fatal("保存失败:", err)
}
}
// 通用加密/解密函数
// 安全加密函数
func secureXor(img *image.RGBA, key []byte) {
keyLen := len(key)
if keyLen == 0 {
log.Fatal("密钥不能为空")
}
bounds := img.Bounds()
data := img.Pix
stride := img.Stride
width := bounds.Dx() * 4 // 每行实际需要的字节数
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
rowStart := (y - bounds.Min.Y) * stride
// 严格限定处理范围为有效像素区
end := rowStart + width
if end > len(data) {
end = len(data)
}
for pos := rowStart; pos < end; pos++ {
data[pos] ^= key[pos%keyLen]
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 KiB