diff --git a/constants/websocket.go b/constants/websocket.go index 4fd14ff5..aea30b29 100644 --- a/constants/websocket.go +++ b/constants/websocket.go @@ -21,11 +21,12 @@ const ( // websocket消息类型(云渲染类别) const ( - WEBSOCKET_RENDER_IMAGE Websocket = "WEBSOCKET_RENDER_IMAGE" //图片渲染消息(1级消息,双向通信) - WEBSOCKET_RENDER_IMAGE_ERR Websocket = "WEBSOCKET_RENDER_IMAGE_ERR" //图片渲染失败消息(1级消息,单向通信) - WEBSOCKET_COMBINE_IMAGE Websocket = "WEBSOCKET_COMBINE_IMAGE" //反回合成刀版图消息(2级消息,单向通信,属于 WEBSOCKET_RENDER_IMAGE 消息的子流程) - WEBSOCKET_ASSEMBLE_RENDER_DATA Websocket = "WEBSOCKET_ASSEMBLE_RENDER_DATA" //组装unity需要的数据 (2级消息,单向通信,属于 WEBSOCKET_RENDER_IMAGE 消息的子流程) - WEBSOCKET_SEND_DATA_TO_UNITY Websocket = "WEBSOCKET_SEND_DATA_TO_UNITY" //发送到unity进行渲染 (2级消息,单向通信,属于 WEBSOCKET_RENDER_IMAGE 消息的子流程) + WEBSOCKET_RENDER_IMAGE Websocket = "WEBSOCKET_RENDER_IMAGE" //图片渲染消息(1级消息,双向通信) + WEBSOCKET_RENDER_IMAGE_ERR Websocket = "WEBSOCKET_RENDER_IMAGE_ERR" //图片渲染失败消息(1级消息,单向通信) + WEBSOCKET_COMBINE_IMAGE Websocket = "WEBSOCKET_COMBINE_IMAGE" //反回合成刀版图消息(2级消息,单向通信,属于 WEBSOCKET_RENDER_IMAGE 消息的子流程) + WEBSOCKET_ASSEMBLE_RENDER_DATA Websocket = "WEBSOCKET_ASSEMBLE_RENDER_DATA" //组装unity需要的数据 (2级消息,单向通信,属于 WEBSOCKET_RENDER_IMAGE 消息的子流程) + WEBSOCKET_SEND_DATA_TO_UNITY Websocket = "WEBSOCKET_SEND_DATA_TO_UNITY" //发送到unity进行渲染 (2级消息,单向通信,属于 WEBSOCKET_RENDER_IMAGE 消息的子流程) + WEBSOCKET_REQUIRE_BROWSER_RESEND_RENDER Websocket = "WEBSOCKET_REQUIRE_BROWSER_RESEND_RENDER" //后端请求前端去重发渲染任务事件(2级消息,单向通信,属于 WEBSOCKET_RENDER_IMAGE 消息的子流程) ) // websocket消息类型(系统数据变更通知) diff --git a/model/gmodel/casbin_rule_gen.go b/model/gmodel/casbin_rule_gen.go index df295df8..57bd8599 100644 --- a/model/gmodel/casbin_rule_gen.go +++ b/model/gmodel/casbin_rule_gen.go @@ -4,16 +4,15 @@ import ( "gorm.io/gorm" ) -// casbin_rule 后台--权限规则表 +// casbin_rule type CasbinRule struct { - Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` // 序号 - PType *string `gorm:"default:'';" json:"p_type"` // - V0 *string `gorm:"default:'';" json:"v0"` // - V1 *string `gorm:"default:'';" json:"v1"` // - V2 *string `gorm:"default:'';" json:"v2"` // - V3 *string `gorm:"default:'';" json:"v3"` // - V4 *string `gorm:"default:'';" json:"v4"` // - V5 *string `gorm:"default:'';" json:"v5"` // + PType *string `gorm:"default:'';" json:"p_type"` // + V0 *string `gorm:"default:'';" json:"v0"` // + V1 *string `gorm:"default:'';" json:"v1"` // + V2 *string `gorm:"default:'';" json:"v2"` // + V3 *string `gorm:"default:'';" json:"v3"` // + V4 *string `gorm:"default:'';" json:"v4"` // + V5 *string `gorm:"default:'';" json:"v5"` // } type CasbinRuleModel struct { db *gorm.DB diff --git a/model/gmodel/fs_shopping_cart_logic.go b/model/gmodel/fs_shopping_cart_logic.go index 5361e195..3c978e6c 100644 --- a/model/gmodel/fs_shopping_cart_logic.go +++ b/model/gmodel/fs_shopping_cart_logic.go @@ -113,8 +113,11 @@ func (s *FsShoppingCartModel) Create(ctx context.Context, data *FsShoppingCart) } // 删除 -func (s *FsShoppingCartModel) Delete(ctx context.Context, userId, id int64) error { - return s.db.WithContext(ctx).Model(&FsShoppingCart{}).Where("user_id = ? and id = ?", userId, id).Delete(&FsShoppingCart{}).Error +func (s *FsShoppingCartModel) Delete(ctx context.Context, userId int64, ids []int64) error { + if len(ids) == 0 { + return nil + } + return s.db.WithContext(ctx).Model(&FsShoppingCart{}).Where("user_id = ? and id in (?)", userId, ids).Delete(&FsShoppingCart{}).Error } // 更新 diff --git a/model/gmodel/ldap_apis_gen.go b/model/gmodel/ldap_apis_gen.go new file mode 100644 index 00000000..659107f3 --- /dev/null +++ b/model/gmodel/ldap_apis_gen.go @@ -0,0 +1,25 @@ +package gmodel + +import ( + "gorm.io/gorm" + "time" +) + +// ldap_apis +type LdapApis struct { + Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` // + Method *string `gorm:"default:'';" json:"method"` // + Path *string `gorm:"default:'';" json:"path"` // + Category *string `gorm:"default:'';" json:"category"` // + Remark *string `gorm:"default:'';" json:"remark"` // + Creator *string `gorm:"default:'';" json:"creator"` // + Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` // + Utime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"utime"` // + Dtime *time.Time `gorm:"index;default:'0000-00-00 00:00:00';" json:"dtime"` // +} +type LdapApisModel struct { + db *gorm.DB + name string +} + +func NewLdapApisModel(db *gorm.DB) *LdapApisModel { return &LdapApisModel{db: db, name: "ldap_apis"} } diff --git a/model/gmodel/ldap_apis_logic.go b/model/gmodel/ldap_apis_logic.go new file mode 100644 index 00000000..e68225aa --- /dev/null +++ b/model/gmodel/ldap_apis_logic.go @@ -0,0 +1,2 @@ +package gmodel +// TODO: 使用model的属性做你想做的 \ No newline at end of file diff --git a/model/gmodel/ldap_casbin_rule_gen.go b/model/gmodel/ldap_casbin_rule_gen.go new file mode 100644 index 00000000..86bd35f5 --- /dev/null +++ b/model/gmodel/ldap_casbin_rule_gen.go @@ -0,0 +1,25 @@ +package gmodel + +import ( + "gorm.io/gorm" +) + +// ldap_casbin_rule 规则权限表 +type LdapCasbinRule struct { + Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` // + Ptype *string `gorm:"default:'';" json:"ptype"` // + V0 *string `gorm:"default:'';" json:"v0"` // + V1 *string `gorm:"default:'';" json:"v1"` // + V2 *string `gorm:"default:'';" json:"v2"` // + V3 *string `gorm:"default:'';" json:"v3"` // + V4 *string `gorm:"default:'';" json:"v4"` // + V5 *string `gorm:"default:'';" json:"v5"` // +} +type LdapCasbinRuleModel struct { + db *gorm.DB + name string +} + +func NewLdapCasbinRuleModel(db *gorm.DB) *LdapCasbinRuleModel { + return &LdapCasbinRuleModel{db: db, name: "ldap_casbin_rule"} +} diff --git a/model/gmodel/ldap_casbin_rule_logic.go b/model/gmodel/ldap_casbin_rule_logic.go new file mode 100644 index 00000000..e68225aa --- /dev/null +++ b/model/gmodel/ldap_casbin_rule_logic.go @@ -0,0 +1,2 @@ +package gmodel +// TODO: 使用model的属性做你想做的 \ No newline at end of file diff --git a/model/gmodel/ldap_menus_gen.go b/model/gmodel/ldap_menus_gen.go new file mode 100644 index 00000000..ffdc6e6e --- /dev/null +++ b/model/gmodel/ldap_menus_gen.go @@ -0,0 +1,29 @@ +package gmodel + +import ( + "gorm.io/gorm" + "time" +) + +// ldap_menus +type LdapMenus struct { + Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` // + Name *string `gorm:"default:'';" json:"name"` // + Title *string `gorm:"default:'';" json:"title"` // + Icon *string `gorm:"default:'';" json:"icon"` // + Path *string `gorm:"default:'';" json:"path"` // + Sort *int64 `gorm:"default:999;" json:"sort"` // + Status *int64 `gorm:"default:1;" json:"status"` // + Creator *string `gorm:"default:'';" json:"creator"` // + Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` // + Utime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"utime"` // + Dtime *time.Time `gorm:"index;default:'0000-00-00 00:00:00';" json:"dtime"` // +} +type LdapMenusModel struct { + db *gorm.DB + name string +} + +func NewLdapMenusModel(db *gorm.DB) *LdapMenusModel { + return &LdapMenusModel{db: db, name: "ldap_menus"} +} diff --git a/model/gmodel/ldap_menus_logic.go b/model/gmodel/ldap_menus_logic.go new file mode 100644 index 00000000..e68225aa --- /dev/null +++ b/model/gmodel/ldap_menus_logic.go @@ -0,0 +1,2 @@ +package gmodel +// TODO: 使用model的属性做你想做的 \ No newline at end of file diff --git a/model/gmodel/ldap_users_gen.go b/model/gmodel/ldap_users_gen.go new file mode 100644 index 00000000..5aee8913 --- /dev/null +++ b/model/gmodel/ldap_users_gen.go @@ -0,0 +1,35 @@ +package gmodel + +import ( + "gorm.io/gorm" + "time" +) + +// ldap_users +type LdapUsers struct { + Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` // + Name *string `gorm:"default:'';" json:"name"` // + Nickname *string `gorm:"default:'';" json:"nickname"` // + Email *string `gorm:"default:'';" json:"email"` // + EnterpriseEmail *string `gorm:"default:'';" json:"enterprise_email"` // + JobTitle *string `gorm:"default:'';" json:"job_title"` // + Mobile *string `gorm:"default:'';" json:"mobile"` // + Gender *int64 `gorm:"default:0;" json:"gender"` // 性别 0未知 1男 2女 + Avatar *string `gorm:"default:'';" json:"avatar"` // + Status *int64 `gorm:"default:1;" json:"status"` // 状态 0禁止 1正常 + Departmentids *string `gorm:"default:'';" json:"departmentIds"` // + EmployeeType *int64 `gorm:"default:0;" json:"employee_type"` // 1:正式员工 2:实习生 3:外包4:劳务 5:顾问 + UserDn *string `gorm:"default:'';" json:"user_dn"` // + JoinTime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"join_time"` // + Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` // + Utime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"utime"` // + Dtime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"dtime"` // +} +type LdapUsersModel struct { + db *gorm.DB + name string +} + +func NewLdapUsersModel(db *gorm.DB) *LdapUsersModel { + return &LdapUsersModel{db: db, name: "ldap_users"} +} diff --git a/model/gmodel/ldap_users_logic.go b/model/gmodel/ldap_users_logic.go new file mode 100644 index 00000000..75df7797 --- /dev/null +++ b/model/gmodel/ldap_users_logic.go @@ -0,0 +1,21 @@ +package gmodel + +import ( + "context" + "errors" + "gorm.io/gorm" +) + +// TODO: 使用model的属性做你想做的 + +func (u *LdapUsersModel) CreateOrUpdate(ctx context.Context, openId string, data *LdapUsers) error { + var info LdapUsers + err := u.db.WithContext(ctx).Where("open_id = ?", openId).Take(&info).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return u.db.WithContext(ctx).Create(&data).Error + } + return err + } + return u.db.WithContext(ctx).Where("open_id = ?", openId).Updates(&data).Error +} diff --git a/model/gmodel/var_gen.go b/model/gmodel/var_gen.go index d7ed9b4c..4b7122fd 100644 --- a/model/gmodel/var_gen.go +++ b/model/gmodel/var_gen.go @@ -119,6 +119,10 @@ type AllModelsGen struct { FsUserStock *FsUserStockModel // fs_user_stock 用户云仓库存 FsWebSet *FsWebSetModel // fs_web_set 网站配置表 FsZipCode *FsZipCodeModel // fs_zip_code 邮编表 + LdapApis *LdapApisModel // ldap_apis + LdapCasbinRule *LdapCasbinRuleModel // ldap_casbin_rule 规则权限表 + LdapMenus *LdapMenusModel // ldap_menus + LdapUsers *LdapUsersModel // ldap_users } @@ -239,6 +243,10 @@ func NewAllModels(gdb *gorm.DB) *AllModelsGen { FsUserStock: NewFsUserStockModel(gdb), FsWebSet: NewFsWebSetModel(gdb), FsZipCode: NewFsZipCodeModel(gdb), + LdapApis: NewLdapApisModel(gdb), + LdapCasbinRule: NewLdapCasbinRuleModel(gdb), + LdapMenus: NewLdapMenusModel(gdb), + LdapUsers: NewLdapUsersModel(gdb), } return models } diff --git a/server/feishu-sync/etc/feishu-sync.yaml b/server/feishu-sync/etc/feishu-sync.yaml deleted file mode 100644 index 03a43b25..00000000 --- a/server/feishu-sync/etc/feishu-sync.yaml +++ /dev/null @@ -1,10 +0,0 @@ -Name: feishu-sync -Host: 0.0.0.0 -Port: 9925 -Timeout: 15000 #服务超时时间(毫秒) -SourceMysql: fsreaderwriter:XErSYmLELKMnf3Dh@tcp(fusen.cdmigcvz3rle.us-east-2.rds.amazonaws.com:3306)/fusen -SourceRabbitMq: "" -Auth: - AccessSecret: fusen2023 - AccessExpire: 2592000 - RefreshAfter: 1592000 diff --git a/server/feishu-sync/feishu-sync.go b/server/feishu-sync/feishu-sync.go deleted file mode 100644 index 140e58b8..00000000 --- a/server/feishu-sync/feishu-sync.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "net/http" - "time" - - "fusenapi/utils/auth" - "fusenapi/utils/fsconfig" - - "fusenapi/server/feishu-sync/internal/config" - "fusenapi/server/feishu-sync/internal/handler" - "fusenapi/server/feishu-sync/internal/svc" - - "github.com/zeromicro/go-zero/rest" -) - -var configFile = flag.String("f", "etc/feishu-sync.yaml", "the config file") - -func main() { - flag.Parse() - - var c config.Config - fsconfig.StartNacosConfig(*configFile, &c, nil) - - c.Timeout = int64(time.Second * 15) - server := rest.MustNewServer(c.RestConf, rest.WithCustomCors(auth.FsCors, func(w http.ResponseWriter) { - })) - defer server.Stop() - - ctx := svc.NewServiceContext(c) - handler.RegisterHandlers(server, ctx) - - fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port) - server.Start() -} diff --git a/server/feishu-sync/internal/config/config.go b/server/feishu-sync/internal/config/config.go deleted file mode 100644 index 1224b8b8..00000000 --- a/server/feishu-sync/internal/config/config.go +++ /dev/null @@ -1,18 +0,0 @@ -package config - -import ( - "fusenapi/server/feishu-sync/internal/types" - "github.com/zeromicro/go-zero/rest" -) - -type Config struct { - rest.RestConf - SourceMysql string - Auth types.Auth - SourceRabbitMq string - FeiShu struct { - ApiHost string - EncryptKey string - VerificationToken string - } -} diff --git a/server/feishu-sync/internal/handler/routes.go b/server/feishu-sync/internal/handler/routes.go deleted file mode 100644 index db0e1b4c..00000000 --- a/server/feishu-sync/internal/handler/routes.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by goctl. DO NOT EDIT. -package handler - -import ( - "net/http" - - "fusenapi/server/feishu-sync/internal/svc" - - "github.com/zeromicro/go-zero/rest" -) - -func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { - server.AddRoutes( - []rest.Route{ - { - Method: http.MethodPost, - Path: "/api/feishu/webhook", - Handler: WebhookHandler(serverCtx), - }, - }, - ) -} diff --git a/server/feishu-sync/internal/handler/webhookhandler.go b/server/feishu-sync/internal/handler/webhookhandler.go deleted file mode 100644 index 5ed0e568..00000000 --- a/server/feishu-sync/internal/handler/webhookhandler.go +++ /dev/null @@ -1,15 +0,0 @@ -package handler - -import ( - "fusenapi/server/feishu-sync/internal/logic" - "fusenapi/server/feishu-sync/internal/svc" - "net/http" -) - -func WebhookHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - // 创建一个业务逻辑层实例 - l := logic.NewWebhookLogic(r.Context(), svcCtx) - l.Webhook(w, r) - } -} diff --git a/server/feishu-sync/internal/logic/user_webhook.go b/server/feishu-sync/internal/logic/user_webhook.go deleted file mode 100644 index a4f45e67..00000000 --- a/server/feishu-sync/internal/logic/user_webhook.go +++ /dev/null @@ -1,138 +0,0 @@ -package logic - -type UserWebhookMsg struct { - Schema string `json:"schema"` - Header struct { - EventId string `json:"event_id"` - EventType string `json:"event_type"` - CreateTime string `json:"create_time"` - Token string `json:"token"` - AppId string `json:"app_id"` - TenantKey string `json:"tenant_key"` - } `json:"header"` - Event struct { - Object struct { - OpenId string `json:"open_id"` - UnionId string `json:"union_id"` - UserId string `json:"user_id"` - Name string `json:"name"` - EnName string `json:"en_name"` - Nickname string `json:"nickname"` - Email string `json:"email"` - EnterpriseEmail string `json:"enterprise_email"` - JobTitle string `json:"job_title"` - Mobile string `json:"mobile"` - Gender int64 `json:"gender"` - Avatar struct { - Avatar72 string `json:"avatar_72"` - Avatar240 string `json:"avatar_240"` - Avatar640 string `json:"avatar_640"` - AvatarOrigin string `json:"avatar_origin"` - } `json:"avatar"` - Status struct { - IsFrozen bool `json:"is_frozen"` - IsResigned bool `json:"is_resigned"` - IsActivated bool `json:"is_activated"` - IsExited bool `json:"is_exited"` - IsUnjoin bool `json:"is_unjoin"` - } `json:"status"` - DepartmentIds []string `json:"department_ids"` - LeaderUserId string `json:"leader_user_id"` - City string `json:"city"` - Country string `json:"country"` - WorkStation string `json:"work_station"` - Joint64ime int64 `json:"join_time"` - EmployeeNo string `json:"employee_no"` - EmployeeType int64 `json:"employee_type"` - Orders []struct { - DepartmentId string `json:"department_id"` - UserOrder int64 `json:"user_order"` - DepartmentOrder int64 `json:"department_order"` - IsPrimaryDept bool `json:"is_primary_dept"` - } `json:"orders"` - CustomAttrs []struct { - Type string `json:"type"` - Id string `json:"id"` - Value struct { - Text string `json:"text"` - Url string `json:"url"` - PcUrl string `json:"pc_url"` - OptionId string `json:"option_id"` - OptionValue string `json:"option_value"` - Name string `json:"name"` - PictureUrl string `json:"picture_url"` - GenericUser struct { - Id string `json:"id"` - Type int64 `json:"type"` - } `json:"generic_user"` - } `json:"value"` - } `json:"custom_attrs"` - JobLevelId string `json:"job_level_id"` - JobFamilyId string `json:"job_family_id"` - DottedLineLeaderUserIds []string `json:"dotted_line_leader_user_ids"` - } `json:"object"` - } `json:"event"` -} - -// 员工增删改信息 -func (l *WebhookLogic) OnUserChange(data []byte) error { - return nil - /*var msg UserWebhookMsg - if err := json.Unmarshal(data, &msg); err != nil { - return err - } - avatar, _ := json.Marshal(msg.Event.Object.Avatar) - isFrozen := int64(0) - if msg.Event.Object.Status.IsFrozen { - isFrozen = 1 - } - isResigned := int64(0) - if msg.Event.Object.Status.IsResigned { - isResigned = 1 - } - isActivated := int64(0) - if msg.Event.Object.Status.IsActivated { - isActivated = 1 - } - isExited := int64(0) - if msg.Event.Object.Status.IsExited { - isExited = 1 - } - isUnjoin := int64(0) - if msg.Event.Object.Status.IsUnjoin { - isUnjoin = 1 - } - departmentIds, _ := json.Marshal(msg.Event.Object.DepartmentIds) - orders, _ := json.Marshal(msg.Event.Object.Orders) - feiShuMsgCreateTimeInt64, err := strconv.ParseInt(msg.Header.CreateTime, 10, 64) - if err != nil { - return err - } - feiShuMsgCreateTime := time.UnixMilli(feiShuMsgCreateTimeInt64) - return l.svcCtx.AllModels.FsFeishuUser.CreateOrUpdate(l.ctx, msg.Header.AppId, msg.Event.Object.OpenId, &gmodel.FsFeishuUser{ - AppId: &msg.Header.AppId, - OpenId: &msg.Event.Object.OpenId, - UnionId: &msg.Event.Object.UnionId, - Name: &msg.Event.Object.Name, - EnName: &msg.Event.Object.EnName, - Nickname: &msg.Event.Object.Nickname, - Email: &msg.Event.Object.Email, - EnterpriseEmail: &msg.Event.Object.EnterpriseEmail, - JobTitle: &msg.Event.Object.JobTitle, - Mobile: &msg.Event.Object.Mobile, - Gender: &msg.Event.Object.Gender, - Avatar: &avatar, - IsFrozen: &isFrozen, - IsResigned: &isResigned, - IsActivated: &isActivated, - IsExited: &isExited, - IsUnjoin: &isUnjoin, - DepartmentIds: &departmentIds, - WorkStation: &msg.Event.Object.WorkStation, - EmployeeNo: &msg.Event.Object.EmployeeNo, - EmployeeType: &msg.Event.Object.EmployeeType, - Orders: &orders, - Ctime: &feiShuMsgCreateTime, - Utime: &feiShuMsgCreateTime, - })*/ -} diff --git a/server/feishu-sync/internal/logic/webhooklogic.go b/server/feishu-sync/internal/logic/webhooklogic.go deleted file mode 100644 index 9977575f..00000000 --- a/server/feishu-sync/internal/logic/webhooklogic.go +++ /dev/null @@ -1,150 +0,0 @@ -package logic - -import ( - "context" - "encoding/json" - "fusenapi/model/gmodel" - "fusenapi/server/feishu-sync/internal/svc" - "fusenapi/utils/feishu" - "github.com/zeromicro/go-zero/core/logx" - "io" - "net/http" - "strconv" - "time" -) - -type WebhookLogic struct { - logx.Logger - ctx context.Context - svcCtx *svc.ServiceContext -} - -func NewWebhookLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WebhookLogic { - return &WebhookLogic{ - Logger: logx.WithContext(ctx), - ctx: ctx, - svcCtx: svcCtx, - } -} - -type EncryptWebhookMsg struct { - Encrypt string `json:"encrypt"` //加密的消息 -} -type WebhookMsg struct { - Type string `json:"type"` - Challenge string `json:"challenge"` - Header map[string]interface{} `json:"header"` -} - -// webhook消息事件header(body参数)基础信息 -type BaseWebhookMsgHeaderType struct { - EventId string `json:"event_id"` //事件id(可作为消息唯一性确认) - EventType string `json:"event_type"` //事件类型 - CreateTime string `json:"create_time"` //创建时间 - Token string `json:"token"` //事件token - AppId string `json:"app_id"` //app id - TenantKey string `json:"tenant_key"` //租户key -} - -func (l *WebhookLogic) Webhook(w http.ResponseWriter, r *http.Request) { - bodyBytes, err := io.ReadAll(r.Body) - if err != nil { - logx.Error("读取请求body失败", err) - return - } - defer r.Body.Close() - //计算签名 - timestamp := r.Header.Get("X-Lark-Request-Timestamp") - nonce := r.Header.Get("X-Lark-Request-Nonce") - signature := r.Header.Get("X-Lark-Signature") - sign := feishu.CalculateFeiShuWebhookSignature(timestamp, nonce, l.svcCtx.Config.FeiShu.EncryptKey, bodyBytes) - if signature != sign { - logx.Error("非法的消息,签名验证不通过", sign, "====", signature) - return - } - var encryptMsg EncryptWebhookMsg - if err = json.Unmarshal(bodyBytes, &encryptMsg); err != nil { - logx.Error("反序列化body失败", err, "body数据:", string(bodyBytes)) - return - } - if encryptMsg.Encrypt == "" { - logx.Error("消息加密信息是空的") - return - } - //解密 - realMsgBytes, err := feishu.DecryptFeiShuWebhookMsg(encryptMsg.Encrypt, l.svcCtx.Config.FeiShu.EncryptKey) - if err != nil { - logx.Error(err) - return - } - //如果只是验证http连接的消息 - var webhookMsg WebhookMsg - if err = json.Unmarshal(realMsgBytes, &webhookMsg); err != nil { - logx.Error("反序列化请求body失败", err, "解密数据:", string(realMsgBytes)) - return - } - //验证连接(直接返回) - if webhookMsg.Type == "url_verification" { - challengeRsp := map[string]string{ - "challenge": webhookMsg.Challenge, - } - b, _ := json.Marshal(challengeRsp) - w.Write(b) - return - } - bodyHeaderByte, err := json.Marshal(webhookMsg.Header) - if err != nil { - logx.Error("序列化请求体header失败:", err) - return - } - var msgHeader BaseWebhookMsgHeaderType - if err = json.Unmarshal(bodyHeaderByte, &msgHeader); err != nil { - logx.Error("反序列化请求体中的header失败", err) - return - } - httpHeaderBytes, _ := json.Marshal(r.Header) - httpHeaderStr := string(httpHeaderBytes) - //解密后的数据 - decryptMsgStr := string(realMsgBytes) - feiShuMsgCreateTimeInt64, err := strconv.ParseInt(msgHeader.CreateTime, 10, 64) - if err != nil { - logx.Error("解析消息时间错误:", err) - return - } - feiShuMsgCreateTime := time.UnixMilli(feiShuMsgCreateTimeInt64) - now := time.Now().UTC() - //把事件加入日志 - err = l.svcCtx.AllModels.FsFeishuWebhookLog.Create(l.ctx, &gmodel.FsFeishuWebhookLog{ - AppId: &msgHeader.AppId, - EventId: &msgHeader.EventId, - EventType: &msgHeader.EventType, - HttpHeader: &httpHeaderStr, - Data: &encryptMsg.Encrypt, - DecryptData: &decryptMsgStr, - MsgCtime: &feiShuMsgCreateTime, - Ctime: &now, - }) - if err != nil { - logx.Error("保存webhook消息日志失败:", err) - } - switch msgHeader.EventType { - case "contact.department.created_v3": //部门新建 - case "contact.department.deleted_v3": //部门删除 - case "contact.department.updated_v3": //部门信息变化 - case "contact.employee_type_enum.actived_v3": //启动人员类型事件 - case "contact.employee_type_enum.created_v3": //新建人员类型事件 - case "contact.employee_type_enum.deactivated_v3": //停用人员类型事件 - case "contact.employee_type_enum.deleted_v3": //删除人员类型事件 - case "contact.employee_type_enum.updated_v3": //修改人员类型名称事件 - case "contact.user.created_v3": //员工入职 - err = l.OnUserChange(realMsgBytes) - case "contact.user.deleted_v3": //员工离职 - err = l.OnUserChange(realMsgBytes) - case "contact.user.updated_v3": //员工信息变化 - err = l.OnUserChange(realMsgBytes) - } - if err != nil { - logx.Error("处理事件错误:", err) - } - return -} diff --git a/server/feishu-sync/internal/svc/servicecontext.go b/server/feishu-sync/internal/svc/servicecontext.go deleted file mode 100644 index 6e5b8149..00000000 --- a/server/feishu-sync/internal/svc/servicecontext.go +++ /dev/null @@ -1,27 +0,0 @@ -package svc - -import ( - "fusenapi/initalize" - "fusenapi/model/gmodel" - "fusenapi/server/feishu-sync/internal/config" - "gorm.io/gorm" -) - -type ServiceContext struct { - Config config.Config - - MysqlConn *gorm.DB - AllModels *gmodel.AllModelsGen - RabbitMq *initalize.RabbitMqHandle -} - -func NewServiceContext(c config.Config) *ServiceContext { - conn := initalize.InitMysql(c.SourceMysql) - - return &ServiceContext{ - Config: c, - MysqlConn: conn, - AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)), - RabbitMq: initalize.InitRabbitMq(c.SourceRabbitMq, nil), - } -} diff --git a/server/feishu-sync/internal/types/types.go b/server/feishu-sync/internal/types/types.go deleted file mode 100644 index b5fd43e5..00000000 --- a/server/feishu-sync/internal/types/types.go +++ /dev/null @@ -1,75 +0,0 @@ -// Code generated by goctl. DO NOT EDIT. -package types - -import ( - "fusenapi/utils/basic" -) - -type Request struct { -} - -type Response struct { - Code int `json:"code"` - Message string `json:"msg"` - Data interface{} `json:"data"` -} - -type Auth struct { - AccessSecret string `json:"accessSecret"` - AccessExpire int64 `json:"accessExpire"` - RefreshAfter int64 `json:"refreshAfter"` -} - -type File struct { - Filename string `fsfile:"filename"` - Header map[string][]string `fsfile:"header"` - Size int64 `fsfile:"size"` - Data []byte `fsfile:"data"` -} - -type Meta struct { - TotalCount int64 `json:"total_count"` - PageCount int64 `json:"page_count"` - CurrentPage int `json:"current_page"` - PerPage int `json:"per_page"` -} - -// Set 设置Response的Code和Message值 -func (resp *Response) Set(Code int, Message string) *Response { - return &Response{ - Code: Code, - Message: Message, - } -} - -// Set 设置整个Response -func (resp *Response) SetWithData(Code int, Message string, Data interface{}) *Response { - return &Response{ - Code: Code, - Message: Message, - Data: Data, - } -} - -// SetStatus 设置默认StatusResponse(内部自定义) 默认msg, 可以带data, data只使用一个参数 -func (resp *Response) SetStatus(sr *basic.StatusResponse, data ...interface{}) *Response { - newResp := &Response{ - Code: sr.Code, - } - if len(data) == 1 { - newResp.Data = data[0] - } - return newResp -} - -// SetStatusWithMessage 设置默认StatusResponse(内部自定义) 非默认msg, 可以带data, data只使用一个参数 -func (resp *Response) SetStatusWithMessage(sr *basic.StatusResponse, msg string, data ...interface{}) *Response { - newResp := &Response{ - Code: sr.Code, - Message: msg, - } - if len(data) == 1 { - newResp.Data = data[0] - } - return newResp -} diff --git a/server/shopping-cart/internal/logic/calculatecartpricelogic.go b/server/shopping-cart/internal/logic/calculatecartpricelogic.go index 0ace472b..617363ee 100644 --- a/server/shopping-cart/internal/logic/calculatecartpricelogic.go +++ b/server/shopping-cart/internal/logic/calculatecartpricelogic.go @@ -116,7 +116,7 @@ func (l *CalculateCartPriceLogic) CalculateCartPrice(req *types.CalculateCartPri if fittingInfo, ok := mapModel[*cart.FittingId]; ok { fittingPrice = *fittingInfo.Price } else { - return errors.New(fmt.Sprintf("cart contain some one witch lose fitting:%d", *cart.FittingId)) + logx.Error(fmt.Sprintf("cart contain some one witch lose fitting:%d", *cart.FittingId)) } } //计算价格 diff --git a/server/shopping-cart/internal/logic/deletecartlogic.go b/server/shopping-cart/internal/logic/deletecartlogic.go index 4c1bc37b..2c7f7f64 100644 --- a/server/shopping-cart/internal/logic/deletecartlogic.go +++ b/server/shopping-cart/internal/logic/deletecartlogic.go @@ -35,7 +35,7 @@ func (l *DeleteCartLogic) DeleteCart(req *types.DeleteCartReq, userinfo *auth.Us return resp.SetStatusWithMessage(basic.CodeUnAuth, "please sign in") } //删除购物车 - if err := l.svcCtx.AllModels.FsShoppingCart.Delete(l.ctx, userinfo.UserId, req.Id); err != nil { + if err := l.svcCtx.AllModels.FsShoppingCart.Delete(l.ctx, userinfo.UserId, req.IdList); err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to delete shopping cart") } diff --git a/server/shopping-cart/internal/logic/getcartslogic.go b/server/shopping-cart/internal/logic/getcartslogic.go index dbe0f267..4a6cbbaa 100644 --- a/server/shopping-cart/internal/logic/getcartslogic.go +++ b/server/shopping-cart/internal/logic/getcartslogic.go @@ -116,14 +116,14 @@ func (l *GetCartsLogic) GetCarts(req *types.GetCartsReq, userinfo *auth.UserInfo fittingPrice := int64(0) if *cart.FittingId > 0 { curFittingInfo, ok := mapModel[*cart.FittingId] - if !ok { - return resp.SetStatusWithMessage(basic.CodeServiceErr, fmt.Sprintf("cart contain some one witch lose fitting:%d", *cart.FittingId)) - } - fittingPrice = *curFittingInfo.Price - //取大的为步进量基数 - if *curFittingInfo.PackedUnit > stepPurchaseQuantity { - stepPurchaseQuantity = *curFittingInfo.PackedUnit + if ok { + fittingPrice = *curFittingInfo.Price + //取大的为步进量基数 + if *curFittingInfo.PackedUnit > stepPurchaseQuantity { + stepPurchaseQuantity = *curFittingInfo.PackedUnit + } } + logx.Error(fmt.Sprintf("cart contain some one witch lose fitting:%d", *cart.FittingId)) } //计算阶梯价格 totalPrice, itemPrice, err := l.svcCtx.Repositories.NewShoppingCart.CaculateStepPrice(*cart.PurchaseQuantity, stepPrice, fittingPrice) diff --git a/server/shopping-cart/internal/types/types.go b/server/shopping-cart/internal/types/types.go index d19cbf50..efe21370 100644 --- a/server/shopping-cart/internal/types/types.go +++ b/server/shopping-cart/internal/types/types.go @@ -35,7 +35,7 @@ type DiyInfo struct { } type DeleteCartReq struct { - Id int64 `json:"id"` //购物车id + IdList []int64 `json:"id_list"` //购物车id } type GetCartsReq struct { diff --git a/server/websocket/internal/logic/rendernotifylogic.go b/server/websocket/internal/logic/rendernotifylogic.go index 42601440..ed545373 100644 --- a/server/websocket/internal/logic/rendernotifylogic.go +++ b/server/websocket/internal/logic/rendernotifylogic.go @@ -114,6 +114,11 @@ func (l *RenderNotifyLogic) RenderNotify(req *types.RenderNotifyReq, userinfo *a if ws.conn != nil { //发送错误信息给前端 ws.renderErrResponse(requestId, info.TemplateTag, info.TaskId, "unity云渲染错误:"+req.Msg, 0, 0, 0, 0, 0, 0, 0) + //发送给前端重发消息 + ws.requestResendRenderResponse(websocket_data.RequestBrowserResendRenderEvent{ + RequestId: info.RequestId, + Description: "unity require resend", + }) logx.Info("渲染失败且发送了失败信息:", req.Msg) } else { logx.Info("渲染失败且找不到ws连接") diff --git a/server/websocket/internal/logic/ws_err_response.go b/server/websocket/internal/logic/ws_err_response.go index 21576076..ae495a86 100644 --- a/server/websocket/internal/logic/ws_err_response.go +++ b/server/websocket/internal/logic/ws_err_response.go @@ -81,3 +81,11 @@ func (w *wsConnectItem) renderErrResponse(requestId, templateTag, taskId, descri } w.sendToOutChan(w.respondDataFormat(constants.WEBSOCKET_RENDER_IMAGE_ERR, data)) } + +// 渲染失败要求重新发起任务 +func (w *wsConnectItem) requestResendRenderResponse(data websocket_data.RequestBrowserResendRenderEvent) { + if w.debug == nil { + data.Description = "" + } + w.sendToOutChan(w.respondDataFormat(constants.WEBSOCKET_REQUIRE_BROWSER_RESEND_RENDER, data)) +} diff --git a/server/websocket/internal/logic/ws_ok_response.go b/server/websocket/internal/logic/ws_ok_response.go index bcfd7cfb..70ac842a 100644 --- a/server/websocket/internal/logic/ws_ok_response.go +++ b/server/websocket/internal/logic/ws_ok_response.go @@ -32,7 +32,7 @@ func (w *wsConnectItem) sendCombineImageStepResponseMessage(requestId, combineIm SizeId: sizeId, ModelId: modelId, TemplateId: templateId, - CombineProcessTime: websocket_data.CombineProcessTime{ + CombineProcessTime: &websocket_data.CombineProcessTime{ CombineTakesTime: combineTakesTime, UploadCombineImageTakesTime: uploadCombineImageTakesTime, }, diff --git a/server/websocket/internal/logic/ws_render_image.go b/server/websocket/internal/logic/ws_render_image.go index 14b6d48b..dea2895c 100644 --- a/server/websocket/internal/logic/ws_render_image.go +++ b/server/websocket/internal/logic/ws_render_image.go @@ -229,7 +229,13 @@ func (w *wsConnectItem) renderImage(renderImageData websocket_data.RenderImageRe } res, err := w.logic.svcCtx.Repositories.ImageHandle.LogoCombine(w.logic.ctx, &combineReq) if err != nil { + //发送渲染错误消息 w.renderErrResponse(renderImageData.RequestId, renderImageData.RenderData.TemplateTag, "", "合成刀版图失败:"+err.Error(), renderImageData.RenderData.ProductId, w.userId, w.guestId, productTemplate.Id, model3dInfo.Id, productSize.Id, *productTemplate.ElementModelId) + //发送给前端重发消息 + w.requestResendRenderResponse(websocket_data.RequestBrowserResendRenderEvent{ + RequestId: renderImageData.RequestId, + Description: "combine require resend", + }) //统计合图失败数 increaseCombineRequestErrorCount(w.userId, w.guestId) logx.Error("合成刀版图失败,合成请求数据:", combineReq, "错误信息:", err) diff --git a/server_api/feishu-sync.api b/server_api/feishu-sync.api deleted file mode 100644 index 31db4bea..00000000 --- a/server_api/feishu-sync.api +++ /dev/null @@ -1,16 +0,0 @@ -syntax = "v1" - -info ( - title: "飞书同步服务"// TODO: add title - desc: // TODO: add description - author: "" - email: "" -) - -import "basic.api" - -service feishu-sync { - //飞书ticket webhook事件接口 - @handler WebhookHandler - post /api/feishu/webhook(request) returns (response); -} \ No newline at end of file diff --git a/server_api/shopping-cart.api b/server_api/shopping-cart.api index e568a7c8..0767dff2 100644 --- a/server_api/shopping-cart.api +++ b/server_api/shopping-cart.api @@ -55,7 +55,7 @@ type DiyInfo { } //删除购物车 type DeleteCartReq { - Id int64 `json:"id"` //购物车id + IdList []int64 `json:"id_list"` //购物车id } //获取购物车列表 diff --git a/utils/feishu/api.go b/utils/feishu/api.go new file mode 100644 index 00000000..2fb73963 --- /dev/null +++ b/utils/feishu/api.go @@ -0,0 +1,40 @@ +package feishu + +import ( + "bytes" + "encoding/json" + "fusenapi/utils/curl" + "time" +) + +type FeiShuApi struct { + AppId string + AppSecret string + ApiHost string +} + +// 获取tenant_access_token +type GetTenantAccessTokenRsp struct { + Code int `json:"code"` + Msg string `json:"msg"` + TenantAccessToken string `json:"tenant_access_token"` + Expire int `json:"expire"` +} + +func (f *FeiShuApi) GetTenantAccessToken() (resp GetTenantAccessTokenRsp, err error) { + url := f.ApiHost + "/open-apis/auth/v3/tenant_access_token/internal" + header := map[string]string{"Content-Type": "application/json; charset=utf-8"} + req := map[string]interface{}{ + "app_secret": f.AppSecret, + "app_id": f.AppId, + } + postData, _ := json.Marshal(req) + rsp, err := curl.ApiCall2(url, "POST", header, bytes.NewReader(postData), time.Second*15) + if err != nil { + return GetTenantAccessTokenRsp{}, err + } + if err = json.Unmarshal(rsp, &resp); err != nil { + return GetTenantAccessTokenRsp{}, err + } + return resp, nil +} diff --git a/utils/websocket_data/render_data.go b/utils/websocket_data/render_data.go index 8d0a8136..22ac1cb3 100644 --- a/utils/websocket_data/render_data.go +++ b/utils/websocket_data/render_data.go @@ -39,12 +39,12 @@ type RenderProcessTime struct { // 合图返回数据 type CombineImageRspMsg struct { - RequestId string `json:"request_id"` - CombineImage string `json:"combine_image"` //刀版图 - SizeId int64 `json:"size_id"` //尺寸id - ModelId int64 `json:"model_id"` - TemplateId int64 `json:"template_id"` - CombineProcessTime CombineProcessTime `json:"combine_process_time"` + RequestId string `json:"request_id"` + CombineImage string `json:"combine_image"` //刀版图 + SizeId int64 `json:"size_id"` //尺寸id + ModelId int64 `json:"model_id"` + TemplateId int64 `json:"template_id"` + CombineProcessTime *CombineProcessTime `json:"combine_process_time"` } type CombineProcessTime struct { CombineTakesTime string `json:"combine_takes_time"` //合图时间 @@ -71,3 +71,9 @@ type ToUnityIdStruct struct { UserId int64 `json:"user_id"` GuestId int64 `json:"guest_id"` } + +// 要求前端重发渲染消息事件结构 +type RequestBrowserResendRenderEvent struct { + RequestId string `json:"request_id"` + Description string `json:"description"` +}