2023-08-31 08:17:32 +00:00
package logic
import (
2023-09-01 07:05:42 +00:00
"encoding/json"
2023-08-31 08:17:32 +00:00
"fmt"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
2023-09-01 02:48:00 +00:00
"fusenapi/utils/check"
2023-08-31 08:17:32 +00:00
"strings"
"context"
"fusenapi/server/info/internal/svc"
"fusenapi/server/info/internal/types"
"github.com/zeromicro/go-zero/core/logx"
"gorm.io/gorm"
)
type InfoLogic struct {
logx . Logger
ctx context . Context
svcCtx * svc . ServiceContext
}
func NewInfoLogic ( ctx context . Context , svcCtx * svc . ServiceContext ) * InfoLogic {
return & InfoLogic {
Logger : logx . WithContext ( ctx ) ,
ctx : ctx ,
svcCtx : svcCtx ,
}
}
// 处理进入前逻辑w,r
// func (l *InfoLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
// }
// 这个与表名强关联
var ModuleTable map [ string ] string = map [ string ] string {
"userinfo" : "fs_user_info" ,
"material" : "fs_user_material" ,
2023-09-25 07:58:33 +00:00
"address" : "fs_address" , // TODO: 地址列表
2023-08-31 08:17:32 +00:00
}
2023-09-01 02:48:00 +00:00
type ModuleQuery struct {
2023-09-01 05:30:34 +00:00
TableName string
2023-09-01 02:48:00 +00:00
ModuleName string
2023-09-01 09:03:27 +00:00
Cond string
2023-09-01 04:22:05 +00:00
ModuleQuery map [ string ] struct { }
}
func ( mquery * ModuleQuery ) EncodeQuery ( field string ) string {
2023-09-01 08:17:40 +00:00
2023-09-01 04:22:05 +00:00
var qstr [ ] byte = [ ] byte ( "JSON_OBJECT(" )
for query := range mquery . ModuleQuery {
2023-09-01 08:23:50 +00:00
if query != "" {
query = "." + query
}
2023-09-01 09:03:27 +00:00
qstr = append ( qstr , [ ] byte ( fmt . Sprintf ( "'%s%s', JSON_EXTRACT(%s,'$%s')," , mquery . ModuleName , query , field , query ) ) ... )
2023-09-01 04:22:05 +00:00
}
if qstr [ len ( qstr ) - 1 ] == ',' {
qstr [ len ( qstr ) - 1 ] = ')'
} else {
qstr = append ( qstr , ')' )
}
return string ( qstr )
2023-09-01 02:48:00 +00:00
}
2023-09-01 09:13:31 +00:00
func ( mquery * ModuleQuery ) EncodeEmpty ( ) map [ string ] any {
var qstr map [ string ] any = make ( map [ string ] any )
for query := range mquery . ModuleQuery {
if query != "" {
query = "." + query
}
k := fmt . Sprintf ( "%s%s" , mquery . ModuleName , query )
2023-09-04 08:23:11 +00:00
qstr [ k ] = nil
2023-09-01 09:13:31 +00:00
}
return qstr
}
2023-09-22 04:09:41 +00:00
func QueryDefault ( conn * gorm . DB , module string , moduleQuery string , tname string ) map [ string ] any {
qname := strings . Split ( moduleQuery , "." )
queryAsName := qname [ len ( qname ) - 1 ]
sqlstr := fmt . Sprintf (
"select JSON_EXTRACT(metadata,'$.%s') as %s from %s where module = '%s' and user_id = 0 and guest_id = 0 order by ctime DESC limit 1" ,
moduleQuery , // logo_selected
queryAsName , // logo_selected
tname , // fs_user_info
module , // profile
)
raw := conn . Raw ( sqlstr )
var info map [ string ] any
err := raw . Scan ( & info ) . Error
if err == gorm . ErrRecordNotFound {
logx . Error ( err )
}
2023-09-22 05:35:05 +00:00
if v , ok := info [ queryAsName ] ; ok {
var qinfo map [ string ] any
err := json . Unmarshal ( [ ] byte ( v . ( string ) ) , & qinfo )
if err != nil {
logx . Error ( err )
} else {
info [ queryAsName ] = qinfo
}
}
2023-09-22 04:09:41 +00:00
return info
}
2023-08-31 08:17:32 +00:00
func ( l * InfoLogic ) Info ( req * types . UserInfoRequest , userinfo * auth . UserInfo ) ( resp * basic . Response ) {
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
// userinfo 传入值时, 一定不为null
2023-09-21 10:12:22 +00:00
//TODO: 可以优化, 合并模块
2023-09-01 09:03:27 +00:00
var condUser string
2023-08-31 08:17:32 +00:00
switch userinfo . GetIdType ( ) {
case auth . IDTYPE_User :
2023-09-01 09:03:27 +00:00
condUser = fmt . Sprintf ( "user_id = %d" , userinfo . UserId )
2023-08-31 08:17:32 +00:00
case auth . IDTYPE_Guest :
2023-09-01 09:03:27 +00:00
condUser = fmt . Sprintf ( "guest_id = %d" , userinfo . GuestId )
2023-08-31 08:17:32 +00:00
default :
2023-09-01 09:03:27 +00:00
condUser = "user_id = 0 and guest_id = 0"
2023-08-31 08:17:32 +00:00
}
2023-09-01 04:22:05 +00:00
var mquerys map [ string ] * ModuleQuery = make ( map [ string ] * ModuleQuery )
2023-08-31 08:17:32 +00:00
var metadict map [ string ] any = make ( map [ string ] any )
for _ , module := range req . Module {
2023-09-01 09:03:27 +00:00
2023-09-01 02:48:00 +00:00
if ! check . CheckModuleQuery ( module ) {
return resp . SetStatusWithMessage ( basic . CodeApiErr , fmt . Sprintf ( "%s format is error" , module ) )
}
2023-08-31 08:17:32 +00:00
mlist := strings . Split ( module , "." )
2023-09-01 07:58:03 +00:00
if len ( mlist ) < 2 {
2023-08-31 08:17:32 +00:00
return resp . SetStatusWithMessage ( basic . CodeApiErr , fmt . Sprintf ( "%s format error" , module ) )
}
mtable := mlist [ 0 ]
tname , ok := ModuleTable [ mtable ]
if ! ok {
return resp . SetStatusWithMessage ( basic . CodeApiErr , fmt . Sprintf ( "%s format error, table %s not found" , module , tname ) )
}
2023-09-01 07:58:03 +00:00
moduleName := mlist [ 1 ]
2023-09-01 09:03:27 +00:00
cond := fmt . Sprintf ( "module = '%s' and %s" , moduleName , condUser )
2023-09-01 08:17:40 +00:00
2023-09-01 04:22:05 +00:00
if mquery , ok := mquerys [ mtable ] ; ok {
2023-09-21 06:53:21 +00:00
mquery . ModuleQuery [ strings . Join ( mlist [ 2 : ] , "." ) ] = struct { } { }
2023-09-01 04:22:05 +00:00
} else {
mquery := & ModuleQuery {
2023-09-01 05:32:17 +00:00
TableName : tname ,
2023-09-01 08:10:32 +00:00
ModuleName : mtable + "." + moduleName ,
2023-09-01 09:03:27 +00:00
Cond : cond ,
2023-09-21 06:53:21 +00:00
ModuleQuery : map [ string ] struct { } { strings . Join ( mlist [ 2 : ] , "." ) : { } } }
2023-09-01 04:22:05 +00:00
mquerys [ mtable ] = mquery
}
2023-09-01 02:48:00 +00:00
}
for _ , mquery := range mquerys {
2023-09-21 03:49:29 +00:00
sqlstr := fmt . Sprintf ( "select id, module, %s as querydata from %s where %s order by ctime DESC limit 1" , mquery . EncodeQuery ( "metadata" ) , mquery . TableName , mquery . Cond )
2023-09-01 06:08:46 +00:00
raw := l . svcCtx . MysqlConn . Raw ( sqlstr )
2023-09-01 06:09:38 +00:00
if raw . Error != nil {
if raw . Error == gorm . ErrRecordNotFound {
continue
} else {
logx . Error ( raw . Error )
return resp . SetStatusWithMessage ( basic . CodeApiErr , raw . Error . Error ( ) )
}
2023-09-01 06:08:46 +00:00
}
2023-09-01 06:25:46 +00:00
var info map [ string ] any = make ( map [ string ] any )
2023-09-01 06:19:13 +00:00
err := raw . Scan ( & info ) . Error
2023-08-31 08:17:32 +00:00
if err == gorm . ErrRecordNotFound {
continue
}
if err != nil {
2023-09-01 05:24:40 +00:00
logx . Error ( err , mquery . EncodeQuery ( "metadata" ) )
2023-08-31 08:17:32 +00:00
return resp . SetStatusWithMessage ( basic . CodeApiErr , err . Error ( ) )
}
2023-09-01 09:03:27 +00:00
queryjson , ok := info [ "querydata" ] . ( string )
if ! ok {
2023-09-01 09:13:31 +00:00
for k , v := range mquery . EncodeEmpty ( ) {
metadict [ k ] = v
}
continue
// return resp.SetStatusWithMessage(basic.CodeDbSqlErr, mquery.ModuleName)
2023-09-01 09:03:27 +00:00
}
2023-09-01 08:31:22 +00:00
2023-09-01 07:05:42 +00:00
var querydata map [ string ] any = make ( map [ string ] any )
2023-09-01 09:03:27 +00:00
err = json . Unmarshal ( [ ] byte ( queryjson ) , & querydata )
2023-09-01 07:05:42 +00:00
if err != nil {
2023-09-01 08:25:17 +00:00
logx . Error ( info )
2023-09-01 07:05:42 +00:00
return resp . SetStatusWithMessage ( basic . CodeApiErr , err . Error ( ) )
}
2023-09-01 06:42:11 +00:00
2023-09-01 07:05:42 +00:00
for k , v := range querydata {
2023-09-01 04:22:05 +00:00
metadict [ k ] = v
}
2023-08-31 08:17:32 +00:00
}
2023-09-22 04:09:41 +00:00
// 隐含白板用户逻辑
if v , ok := metadict [ "userinfo.profile" ] ; ok {
if v == nil {
2023-09-22 04:28:38 +00:00
2023-09-22 04:09:41 +00:00
info := QueryDefault ( l . svcCtx . MysqlConn , "profile" , "logo_selected" , "fs_user_info" )
metadict [ "userinfo.profile" ] = info
} else {
profileDict := v . ( map [ string ] any )
if _ , ok := profileDict [ "logo_selected" ] ; ! ok {
info := QueryDefault ( l . svcCtx . MysqlConn , "profile" , "logo_selected" , "fs_user_info" )
profileDict [ "logo_selected" ] = info [ "logo_selected" ]
}
}
} else if v , ok := metadict [ "userinfo.profile.logo_selected" ] ; ok {
if v == nil {
info := QueryDefault ( l . svcCtx . MysqlConn , "profile" , "logo_selected" , "fs_user_info" )
metadict [ "userinfo.profile.logo_selected" ] = info
}
2023-09-22 04:28:38 +00:00
} else {
var info map [ string ] any
for k , v := range metadict {
if v == nil {
if strings . HasPrefix ( k , "userinfo.profile.logo_selected" ) {
if info == nil {
info = QueryDefault ( l . svcCtx . MysqlConn , "profile" , "logo_selected" , "fs_user_info" )
}
curValue , err := GetMapValueByKey ( info , strings . Split ( k , "." ) [ 2 : ] )
if err != nil {
2023-09-22 04:31:24 +00:00
logx . Error ( err , info )
2023-09-22 04:28:38 +00:00
continue
// return resp.SetStatus(basic.CodeOK, metadict)
}
metadict [ k ] = curValue
// curValue
}
}
}
2023-09-22 04:09:41 +00:00
}
2023-08-31 08:17:32 +00:00
return resp . SetStatus ( basic . CodeOK , metadict )
}
2023-09-22 04:28:38 +00:00
func GetMapValueByKey ( info map [ string ] interface { } , keys [ ] string ) ( interface { } , error ) {
// keys := strings.Split(key, ".")[2:]
for _ , k := range keys {
if cur , ok := info [ k ] ; ok {
if curMap , ok := cur . ( map [ string ] interface { } ) ; ok {
info = curMap
} else {
2023-09-22 05:37:23 +00:00
// logx.Error(cur)
2023-09-22 05:18:31 +00:00
return cur , nil
2023-09-22 04:28:38 +00:00
}
} else {
2023-09-22 04:31:24 +00:00
return nil , fmt . Errorf ( "info keys is not exists %#v" , keys )
2023-09-22 04:28:38 +00:00
}
}
return info , nil
}
2023-08-31 08:17:32 +00:00
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
// func (l *InfoLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
// // httpx.OkJsonCtx(r.Context(), w, resp)
// }