add face recognition

This commit is contained in:
2025-01-22 10:36:28 +08:00
parent eab806fb9b
commit c6af9a0461
47 changed files with 3621 additions and 454 deletions

View File

@@ -18,6 +18,12 @@ CpuThreshold: 900
MaxBytes: 10485760
# 是否打印详细日志
Verbose: false
# RPC 配置
AiSvcRpc:
Etcd:
Hosts:
- 127.0.0.1:2379
Key: aisvc.rpc
# 日志配置
Log:
# 服务名称
@@ -161,4 +167,7 @@ SMS:
# 短信宝用户账号
Username: landaiqing
# 短信宝用户密码
Password: $LDQ20020618xxx$
Password: $LDQ20020618xxx$
Map:
# 高德地图API Key
Key: 54823a494909959a9c8cd8af101bbc32

View File

@@ -1,10 +1,14 @@
package config
import "github.com/zeromicro/go-zero/rest"
import (
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/zrpc"
)
type Config struct {
rest.RestConf
Web struct {
AiSvcRpc zrpc.RpcClientConf
Web struct {
URL string
}
Auth struct {
@@ -67,4 +71,7 @@ type Config struct {
Password string
}
}
Map struct {
Key string
}
}

View File

@@ -2,12 +2,23 @@ package storage
import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/zeromicro/go-zero/core/logx"
"io"
"mime/multipart"
"net/http"
"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/encrypt"
"schisandra-album-cloud-microservices/common/gao_map"
"schisandra-album-cloud-microservices/common/storage/config"
"strconv"
"strings"
"time"
)
type UploadFileLogic struct {
@@ -25,36 +36,199 @@ func NewUploadFileLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Upload
}
func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
// 获取用户 ID
uid, err := l.getUserID()
if err != nil {
return "", err
}
// 解析上传的文件
file, header, err := l.getUploadedFile(r)
if err != nil {
return "", err
}
defer func(file multipart.File) {
_ = file.Close()
}(file)
// 解析 AI 识别结果
result, err := l.parseAIRecognitionResult(r)
if err != nil {
return "", err
}
var faceId int64
bytes, err := io.ReadAll(file)
if err != nil {
return "", err
}
// 人脸识别
face, err := l.svcCtx.AiSvcRpc.FaceRecognition(l.ctx, &pb.FaceRecognitionRequest{Face: bytes, UserId: uid})
if err != nil {
return "", err
}
if face != nil {
faceId = face.GetFaceId()
}
// 解析 EXIF 信息
exif, err := l.parseExifData(result.Exif)
if err != nil {
return "", err
}
// 提取拍摄时间
originalDateTime, err := l.extractOriginalDateTime(exif)
if err != nil {
return "", err
}
// 提取 GPS 信息
latitude, longitude := l.extractGPSCoordinates(exif)
// 根据 GPS 信息获取地理位置信息
locationString, gpsString, err := l.getGeoLocation(latitude, longitude)
if err != nil {
return "", err
}
// 上传文件到 OSS
if err = l.uploadFileToOSS(uid, header, file); err != nil {
return "", err
}
// 将 EXIF 和文件信息存入数据库
if err = l.saveFileInfoToDB(uid, header, result, originalDateTime, gpsString, locationString, exif, faceId); err != nil {
return "", err
}
return "success", nil
}
// 获取用户 ID
func (l *UploadFileLogic) getUserID() (string, error) {
uid, ok := l.ctx.Value("user_id").(string)
if !ok {
return "", errors.New("user_id not found")
}
return uid, nil
}
// 解析上传的文件
func (l *UploadFileLogic) getUploadedFile(r *http.Request) (multipart.File, *multipart.FileHeader, error) {
file, header, err := r.FormFile("file")
if err != nil {
return "", errors.New("file not found")
return nil, nil, errors.New("file not found")
}
defer file.Close()
//formValue := r.PostFormValue("result")
//
//var result types.File
//err = json.Unmarshal([]byte(formValue), &result)
//if err != nil {
// return "", errors.New("invalid result")
//}
//fmt.Println(result)
return file, header, nil
}
// 解析 AI 识别结果
func (l *UploadFileLogic) parseAIRecognitionResult(r *http.Request) (types.File, error) {
formValue := r.PostFormValue("data")
var result types.File
if err := json.Unmarshal([]byte(formValue), &result); err != nil {
return result, errors.New("invalid result")
}
return result, nil
}
// 解析 EXIF 数据
func (l *UploadFileLogic) parseExifData(exifData interface{}) (map[string]interface{}, error) {
marshaledExif, err := json.Marshal(exifData)
if err != nil {
return nil, errors.New("invalid exif")
}
var exif map[string]interface{}
if err = json.Unmarshal(marshaledExif, &exif); err != nil {
return nil, errors.New("invalid exif")
}
return exif, nil
}
// 提取拍摄时间
func (l *UploadFileLogic) extractOriginalDateTime(exif map[string]interface{}) (string, error) {
if dateTimeOriginal, ok := exif["DateTimeOriginal"].(string); ok {
parsedTime, err := time.Parse(time.RFC3339, dateTimeOriginal)
if err == nil {
return parsedTime.Format("2006-01-02 15:04:05"), nil
}
}
return "", nil
}
// 提取 GPS 信息
func (l *UploadFileLogic) extractGPSCoordinates(exif map[string]interface{}) (float64, float64) {
var latitude, longitude float64
if lat, ok := exif["latitude"].(float64); ok {
latitude = lat
}
if long, ok := exif["longitude"].(float64); ok {
longitude = long
}
return latitude, longitude
}
// 根据 GPS 信息获取地理位置信息
func (l *UploadFileLogic) getGeoLocation(latitude, longitude float64) (string, string, error) {
if latitude == 0 || longitude == 0 {
return "", "", nil
}
gpsString := fmt.Sprintf("[%f,%f]", latitude, longitude)
request := gao_map.ReGeoRequest{Location: fmt.Sprintf("%f,%f", latitude, longitude)}
location, err := l.svcCtx.GaoMap.Location.ReGeo(&request)
if err != nil {
return "", "", errors.New("regeo failed")
}
addressInfo := map[string]string{}
if location.ReGeoCode.AddressComponent.Country != "" {
addressInfo["county"] = location.ReGeoCode.AddressComponent.Country
}
if location.ReGeoCode.AddressComponent.Province != "" {
addressInfo["province"] = location.ReGeoCode.AddressComponent.Province
}
if location.ReGeoCode.AddressComponent.City != "" {
addressInfo["city"] = location.ReGeoCode.AddressComponent.City.(string)
}
if location.ReGeoCode.AddressComponent.District != "" {
addressInfo["district"] = location.ReGeoCode.AddressComponent.District.(string)
}
if location.ReGeoCode.AddressComponent.Township != "" {
addressInfo["township"] = location.ReGeoCode.AddressComponent.Township
}
locationString := ""
if len(addressInfo) > 0 {
addressJSON, err := json.Marshal(addressInfo)
if err != nil {
return "", "", errors.New("marshal address info failed")
}
locationString = string(addressJSON)
}
return locationString, gpsString, nil
}
// 上传文件到 OSS
func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHeader, file multipart.File) error {
ossConfig := l.svcCtx.DB.ScaStorageConfig
dbConfig, err := ossConfig.Where(ossConfig.UserID.Eq(uid)).First()
if err != nil {
return "", errors.New("oss config not found")
return errors.New("oss config not found")
}
accessKey, err := encrypt.Decrypt(dbConfig.AccessKey, l.svcCtx.Config.Encrypt.Key)
if err != nil {
return "", errors.New("decrypt access key failed")
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")
return errors.New("decrypt secret key failed")
}
storageConfig := &config.StorageConfig{
Provider: dbConfig.Type,
Endpoint: dbConfig.Endpoint,
@@ -63,13 +237,48 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
BucketName: dbConfig.Bucket,
Region: dbConfig.Region,
}
service, err := l.svcCtx.StorageManager.GetStorage(uid, storageConfig)
if err != nil {
return "", errors.New("get storage failed")
return errors.New("get storage failed")
}
result, err := service.UploadFileSimple(l.ctx, dbConfig.Bucket, header.Filename, file, map[string]string{})
_, err = service.UploadFileSimple(l.ctx, dbConfig.Bucket, header.Filename, file, map[string]string{})
if err != nil {
return "", errors.New("upload file failed")
return errors.New("upload file failed")
}
return *result.ContentMD5, nil
return nil
}
// 将 EXIF 和文件信息存入数据库
func (l *UploadFileLogic) saveFileInfoToDB(uid string, header *multipart.FileHeader, result types.File, originalDateTime, gpsString, locationString string, exif map[string]interface{}, faceId int64) error {
exifJSON, err := json.Marshal(exif)
if err != nil {
return errors.New("marshal exif failed")
}
scaStorageInfo := &model.ScaStorageInfo{
UserID: uid,
Provider: result.FileType,
Bucket: result.TopCategory,
FileName: header.Filename,
FileSize: strconv.FormatInt(header.Size, 10),
FileType: result.FileType,
Landscape: result.Landscape,
Objects: strings.Join(result.ObjectArray, ", "),
Anime: strconv.FormatBool(result.IsAnime),
Category: result.TopCategory,
Screenshot: strconv.FormatBool(result.IsScreenshot),
OriginalTime: originalDateTime,
Gps: gpsString,
Location: locationString,
Exif: string(exifJSON),
FaceID: faceId,
}
err = l.svcCtx.DB.ScaStorageInfo.Create(scaStorageInfo)
if err != nil {
return errors.New("create storage info failed")
}
return nil
}

View File

@@ -73,7 +73,7 @@ func (l *RefreshTokenLogic) RefreshToken(r *http.Request) (resp *types.RefreshTo
GeneratedIP: redisTokenData.GeneratedIP,
UpdatedAt: time.Now().Format(constant.TimeFormat),
}
err = l.svcCtx.RedisClient.Set(l.ctx, constant.UserTokenPrefix+refreshToken.UserID, redisToken, time.Hour*24*7).Err()
err = l.svcCtx.RedisClient.Set(l.ctx, constant.UserTokenPrefix+refreshToken.UserID, redisToken, time.Hour*24*3).Err()
if err != nil {
return nil, err
}

View File

@@ -8,8 +8,10 @@ import (
"github.com/wenlng/go-captcha/v2/rotate"
"github.com/wenlng/go-captcha/v2/slide"
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/zrpc"
sensitive "github.com/zmexing/go-sensitive-word"
"go.mongodb.org/mongo-driver/v2/mongo"
"schisandra-album-cloud-microservices/app/aisvc/rpc/client/aiservice"
"schisandra-album-cloud-microservices/app/auth/api/internal/config"
"schisandra-album-cloud-microservices/app/auth/api/internal/middleware"
"schisandra-album-cloud-microservices/app/auth/model/mongodb"
@@ -17,16 +19,18 @@ import (
"schisandra-album-cloud-microservices/app/auth/model/mysql/query"
"schisandra-album-cloud-microservices/common/captcha/initialize"
"schisandra-album-cloud-microservices/common/casbinx"
"schisandra-album-cloud-microservices/common/gao_map"
"schisandra-album-cloud-microservices/common/ip2region"
"schisandra-album-cloud-microservices/common/redisx"
"schisandra-album-cloud-microservices/common/sensitivex"
"schisandra-album-cloud-microservices/common/storage"
storage2 "schisandra-album-cloud-microservices/common/storage/manager"
"schisandra-album-cloud-microservices/common/storage/manager"
"schisandra-album-cloud-microservices/common/wechat_official"
)
type ServiceContext struct {
Config config.Config
AiSvcRpc aiservice.AiService
SecurityHeadersMiddleware rest.Middleware
CasbinVerifyMiddleware rest.Middleware
AuthorizationMiddleware rest.Middleware
@@ -40,7 +44,8 @@ type ServiceContext struct {
RotateCaptcha rotate.Captcha
SlideCaptcha slide.Captcha
Sensitive *sensitive.Manager
StorageManager *storage2.Manager
StorageManager *manager.Manager
GaoMap *gao_map.AmapClient
}
func NewServiceContext(c config.Config) *ServiceContext {
@@ -63,5 +68,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
MongoClient: mongodb.NewMongoDB(c.Mongo.Uri, c.Mongo.Username, c.Mongo.Password, c.Mongo.AuthSource, c.Mongo.Database),
Sensitive: sensitivex.NewSensitive(),
StorageManager: storage.InitStorageManager(),
GaoMap: gao_map.NewAmapClient(c.Map.Key, ""),
AiSvcRpc: aiservice.NewAiService(zrpc.MustNewClient(c.AiSvcRpc)),
}
}

View File

@@ -2,13 +2,11 @@ package types
// File represents a file uploaded by the user.
type File struct {
UID string `json:"uid"`
FileName string `json:"fileName"`
FileType string `json:"fileType"`
DetectionResult struct {
IsAnime bool `json:"isAnime"`
HasFace bool `json:"hasFace"`
ObjectArray []string `json:"objectArray"`
Landscape string `json:"landscape"`
}
FileType string `json:"fileType"`
IsAnime bool `json:"isAnime"`
ObjectArray []string `json:"objectArray"`
Landscape string `json:"landscape"`
TopCategory string `json:"topCategory"`
IsScreenshot bool `json:"isScreenshot"`
Exif any `json:"exif"`
}

View File

@@ -99,9 +99,41 @@ func main() {
fieldOpts := []gen.ModelOpt{jsonField, idField, autoUpdateTimeField, autoCreateTimeField, softDeleteField, versionField}
// 创建全部模型文件, 并覆盖前面创建的同名模型
allModel := g.GenerateAllTable(fieldOpts...)
scaAuthMenu := g.GenerateModel("sca_auth_menu", fieldOpts...)
scaAuthPermissionRule := g.GenerateModel("sca_auth_permission_rule", fieldOpts...)
scaAuthRole := g.GenerateModel("sca_auth_role", fieldOpts...)
scaAuthUser := g.GenerateModel("sca_auth_user", fieldOpts...)
scaAuthUserDevice := g.GenerateModel("sca_auth_user_device", fieldOpts...)
scaAuthUserSocial := g.GenerateModel("sca_auth_user_social", fieldOpts...)
scaCommentReply := g.GenerateModel("sca_comment_reply", fieldOpts...)
scaCommentLikes := g.GenerateModel("sca_comment_likes", fieldOpts...)
scaMessageReport := g.GenerateModel("sca_message_report", fieldOpts...)
scaStorageConfig := g.GenerateModel("sca_storage_config", fieldOpts...)
scaStorageInfo := g.GenerateModel("sca_storage_info", fieldOpts...)
scaStorageTag := g.GenerateModel("sca_storage_tag", fieldOpts...)
scaStorageTagInfo := g.GenerateModel("sca_storage_tag_info", fieldOpts...)
scaUserFollows := g.GenerateModel("sca_user_follows", fieldOpts...)
scaUserLevel := g.GenerateModel("sca_user_level", fieldOpts...)
scaUserMessage := g.GenerateModel("sca_user_message", fieldOpts...)
g.ApplyBasic(allModel...)
g.ApplyBasic(
scaAuthMenu,
scaAuthPermissionRule,
scaAuthRole,
scaAuthUser,
scaAuthUserDevice,
scaAuthUserSocial,
scaCommentReply,
scaCommentLikes,
scaMessageReport,
scaStorageConfig,
scaStorageInfo,
scaStorageTag,
scaStorageTagInfo,
scaUserFollows,
scaUserLevel,
scaUserMessage,
)
g.Execute()
}

View File

@@ -14,24 +14,29 @@ const TableNameScaStorageInfo = "sca_storage_info"
// ScaStorageInfo mapped from table <sca_storage_info>
type ScaStorageInfo 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);not null;comment:用户ID" json:"user_id"` // 用户ID
Storage string `gorm:"column:storage;type:varchar(50);comment:存储空间" json:"storage"` // 存储空间
Bucket string `gorm:"column:bucket;type:varchar(50);comment:存储桶" json:"bucket"` // 存储桶
Type string `gorm:"column:type;type:varchar(50);comment:类型" json:"type"` // 类型
Path string `gorm:"column:path;type:varchar(255);comment:路径" json:"path"` // 路径
FileName string `gorm:"column:file_name;type:varchar(100);comment:名称" json:"file_name"` // 名称
Category string `gorm:"column:category;type:varchar(50);comment:分类" json:"category"` // 分类
Loaction string `gorm:"column:loaction;type:varchar(100);comment:地址" json:"loaction"` // 地址
Hash string `gorm:"column:hash;type:varchar(255);comment:哈希值" json:"hash"` // 哈希值
Anime string `gorm:"column:anime;type:varchar(50);comment:是否是动漫图片" json:"anime"` // 是否是动漫图片
HasFace string `gorm:"column:has_face;type:varchar(50);comment:是否人像" json:"has_face"` // 是否人像
FaceID int64 `gorm:"column:face_id;type:bigint(20);comment:人像ID" json:"face_id"` // 人像ID
Landscape string `gorm:"column:landscape;type:varchar(50);comment:风景类型" json:"landscape"` // 风景类型
Objects string `gorm:"column:objects;type:varchar(50);comment:对象识别" json:"objects"` // 对象识别
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);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"` // 路径
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"` // 文件类型
Category string `gorm:"column:category;type:varchar(50);comment:分类" json:"category"` // 分类
Tags string `gorm:"column:tags;type:varchar(255);comment:标签" json:"tags"` // 标签
Location string `gorm:"column:location;type:varchar(100);comment:地址" json:"location"` // 地址
Hash string `gorm:"column:hash;type:varchar(255);comment:哈希值" json:"hash"` // 哈希值
Anime string `gorm:"column:anime;type:varchar(50);comment:是否是动漫图片" json:"anime"` // 是否是动漫图片
FaceID int64 `gorm:"column:face_id;type:bigint(20);comment:人像ID" json:"face_id"` // 人像ID
Landscape string `gorm:"column:landscape;type:varchar(50);comment:风景类型" json:"landscape"` // 风景类型
Objects string `gorm:"column:objects;type:varchar(50);comment:对象识别" json:"objects"` // 对象识别
OriginalTime string `gorm:"column:original_time;type:varchar(50);comment:拍摄时间" json:"original_time"` // 拍摄时间
Gps string `gorm:"column:gps;type:varchar(255);comment:GPS" json:"gps"` // GPS
Screenshot string `gorm:"column:screenshot;type:varchar(50);comment:是否是截图" json:"screenshot"` // 是否是截图
Exif string `gorm:"column:exif;type:json;comment:exif 信息" json:"exif"` // exif 信息
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 ScaStorageInfo's table name

View File

@@ -29,19 +29,24 @@ func newScaStorageInfo(db *gorm.DB, opts ...gen.DOOption) scaStorageInfo {
_scaStorageInfo.ALL = field.NewAsterisk(tableName)
_scaStorageInfo.ID = field.NewInt64(tableName, "id")
_scaStorageInfo.UserID = field.NewString(tableName, "user_id")
_scaStorageInfo.Storage = field.NewString(tableName, "storage")
_scaStorageInfo.Provider = field.NewString(tableName, "provider")
_scaStorageInfo.Bucket = field.NewString(tableName, "bucket")
_scaStorageInfo.Type = field.NewString(tableName, "type")
_scaStorageInfo.Path = field.NewString(tableName, "path")
_scaStorageInfo.FileName = field.NewString(tableName, "file_name")
_scaStorageInfo.FileSize = field.NewString(tableName, "file_size")
_scaStorageInfo.FileType = field.NewString(tableName, "file_type")
_scaStorageInfo.Category = field.NewString(tableName, "category")
_scaStorageInfo.Loaction = field.NewString(tableName, "loaction")
_scaStorageInfo.Tags = field.NewString(tableName, "tags")
_scaStorageInfo.Location = field.NewString(tableName, "location")
_scaStorageInfo.Hash = field.NewString(tableName, "hash")
_scaStorageInfo.Anime = field.NewString(tableName, "anime")
_scaStorageInfo.HasFace = field.NewString(tableName, "has_face")
_scaStorageInfo.FaceID = field.NewInt64(tableName, "face_id")
_scaStorageInfo.Landscape = field.NewString(tableName, "landscape")
_scaStorageInfo.Objects = field.NewString(tableName, "objects")
_scaStorageInfo.OriginalTime = field.NewString(tableName, "original_time")
_scaStorageInfo.Gps = field.NewString(tableName, "gps")
_scaStorageInfo.Screenshot = field.NewString(tableName, "screenshot")
_scaStorageInfo.Exif = field.NewString(tableName, "exif")
_scaStorageInfo.CreatedAt = field.NewTime(tableName, "created_at")
_scaStorageInfo.UpdatedAt = field.NewTime(tableName, "updated_at")
_scaStorageInfo.DeletedAt = field.NewField(tableName, "deleted_at")
@@ -54,25 +59,30 @@ func newScaStorageInfo(db *gorm.DB, opts ...gen.DOOption) scaStorageInfo {
type scaStorageInfo struct {
scaStorageInfoDo
ALL field.Asterisk
ID field.Int64 // 主键
UserID field.String // 用户ID
Storage field.String // 存储空间
Bucket field.String // 存储桶
Type field.String // 类型
Path field.String // 路径
FileName field.String // 名称
Category field.String // 分类
Loaction field.String // 地址
Hash field.String // 哈希值
Anime field.String // 是否是动漫图片
HasFace field.String // 是否人像
FaceID field.Int64 // 人像ID
Landscape field.String // 风景类型
Objects field.String // 对象识别
CreatedAt field.Time // 创建时间
UpdatedAt field.Time // 更新时间
DeletedAt field.Field // 删除时间
ALL field.Asterisk
ID field.Int64 // 主键
UserID field.String // 用户ID
Provider field.String // 供应商
Bucket field.String // 存储桶
Path field.String // 路径
FileName field.String // 文件名称
FileSize field.String // 文件大小
FileType field.String // 文件类型
Category field.String // 分类
Tags field.String // 标签
Location field.String // 地址
Hash field.String // 哈希值
Anime field.String // 是否是动漫图片
FaceID field.Int64 // 人像ID
Landscape field.String // 风景类型
Objects field.String // 对象识别
OriginalTime field.String // 拍摄时间
Gps field.String // GPS
Screenshot field.String // 是否是截图
Exif field.String // exif 信息
CreatedAt field.Time // 创建时间
UpdatedAt field.Time // 更新时间
DeletedAt field.Field // 删除时间
fieldMap map[string]field.Expr
}
@@ -91,19 +101,24 @@ func (s *scaStorageInfo) updateTableName(table string) *scaStorageInfo {
s.ALL = field.NewAsterisk(table)
s.ID = field.NewInt64(table, "id")
s.UserID = field.NewString(table, "user_id")
s.Storage = field.NewString(table, "storage")
s.Provider = field.NewString(table, "provider")
s.Bucket = field.NewString(table, "bucket")
s.Type = field.NewString(table, "type")
s.Path = field.NewString(table, "path")
s.FileName = field.NewString(table, "file_name")
s.FileSize = field.NewString(table, "file_size")
s.FileType = field.NewString(table, "file_type")
s.Category = field.NewString(table, "category")
s.Loaction = field.NewString(table, "loaction")
s.Tags = field.NewString(table, "tags")
s.Location = field.NewString(table, "location")
s.Hash = field.NewString(table, "hash")
s.Anime = field.NewString(table, "anime")
s.HasFace = field.NewString(table, "has_face")
s.FaceID = field.NewInt64(table, "face_id")
s.Landscape = field.NewString(table, "landscape")
s.Objects = field.NewString(table, "objects")
s.OriginalTime = field.NewString(table, "original_time")
s.Gps = field.NewString(table, "gps")
s.Screenshot = field.NewString(table, "screenshot")
s.Exif = field.NewString(table, "exif")
s.CreatedAt = field.NewTime(table, "created_at")
s.UpdatedAt = field.NewTime(table, "updated_at")
s.DeletedAt = field.NewField(table, "deleted_at")
@@ -123,22 +138,27 @@ func (s *scaStorageInfo) GetFieldByName(fieldName string) (field.OrderExpr, bool
}
func (s *scaStorageInfo) fillFieldMap() {
s.fieldMap = make(map[string]field.Expr, 18)
s.fieldMap = make(map[string]field.Expr, 23)
s.fieldMap["id"] = s.ID
s.fieldMap["user_id"] = s.UserID
s.fieldMap["storage"] = s.Storage
s.fieldMap["provider"] = s.Provider
s.fieldMap["bucket"] = s.Bucket
s.fieldMap["type"] = s.Type
s.fieldMap["path"] = s.Path
s.fieldMap["file_name"] = s.FileName
s.fieldMap["file_size"] = s.FileSize
s.fieldMap["file_type"] = s.FileType
s.fieldMap["category"] = s.Category
s.fieldMap["loaction"] = s.Loaction
s.fieldMap["tags"] = s.Tags
s.fieldMap["location"] = s.Location
s.fieldMap["hash"] = s.Hash
s.fieldMap["anime"] = s.Anime
s.fieldMap["has_face"] = s.HasFace
s.fieldMap["face_id"] = s.FaceID
s.fieldMap["landscape"] = s.Landscape
s.fieldMap["objects"] = s.Objects
s.fieldMap["original_time"] = s.OriginalTime
s.fieldMap["gps"] = s.Gps
s.fieldMap["screenshot"] = s.Screenshot
s.fieldMap["exif"] = s.Exif
s.fieldMap["created_at"] = s.CreatedAt
s.fieldMap["updated_at"] = s.UpdatedAt
s.fieldMap["deleted_at"] = s.DeletedAt