diff --git a/app/api/config.go b/app/api/config.go index aced6e9..9ce1ed4 100644 --- a/app/api/config.go +++ b/app/api/config.go @@ -126,11 +126,30 @@ func (*Config) Breakdown(c *gin.Context) { } func (*Config) BreakdownAdd(c *gin.Context) { - + form := &struct { + Title string `json:"title" form:"title" binding:"required"` + Remark string `json:"remark" form:"remark"` + }{} + if err := bind(form)(c); err != nil { + APIFailure(err.(error))(c) + return + } + err := config.NewBreakdown()(getSession()(c).(*service.Session)).Form(0, form.Title, form.Remark) + APIResponse(err)(c) } func (*Config) BreakdownEdit(c *gin.Context) { - + form := &struct { + IDStringForm + Title string `json:"title" form:"title" binding:"required"` + Remark string `json:"remark" form:"remark"` + }{} + if err := bind(form)(c); err != nil { + APIFailure(err.(error))(c) + return + } + err := config.NewBreakdown()(getSession()(c).(*service.Session)).Form(form.Convert(), form.Title, form.Remark) + APIResponse(err)(c) } func (*Config) BreakdownDelete(c *gin.Context) { diff --git a/app/api/menu.go b/app/api/menu.go index cd0a6be..b2babb0 100644 --- a/app/api/menu.go +++ b/app/api/menu.go @@ -40,7 +40,7 @@ type ( * @apiSuccess (200) {Number} code 成功响应状态码! * @apiSuccess (200) {String} msg 成功提示 * @apiSuccess (200) {Array} data 具体信息 - * @apiSuccess (200) {Number} data.id 菜单ID + * @apiSuccess (200) {String} data.id 菜单ID * @apiSuccess (200) {Number} data.parent_id 父级ID * @apiSuccess (200) {String} data.name 菜单名称 * @apiSuccess (200) {Number} data.kind 类型(1:目录,2:菜单) @@ -54,7 +54,7 @@ type ( * "code": 200 * "msg": "ok" * "data": [ - * "id": 1, + * "id": "qeqwe", * "parent_id": 0, * "name": "系统管理", * "kind": 1, @@ -62,7 +62,7 @@ type ( * "component": "" * "children": [ * { - * "id": 2, + * "id": "23123asqw", * "parent_id": 1, * "name": "用户管理", * "kind": 1, diff --git a/app/api/role.go b/app/api/role.go index 3f29d36..9693742 100644 --- a/app/api/role.go +++ b/app/api/role.go @@ -105,6 +105,8 @@ func (a *Role) Delete(c *gin.Context) { * * @apiHeader {string} x-token token * + * @apiParam {Number} role_id 角色ID + * * @apiSuccess (200) {Number} code 成功响应状态码! * @apiSuccess (200) {String} msg 成功提示 * @apiSuccess (200) {Array} data 具体信息 @@ -144,13 +146,15 @@ func (a *Role) Delete(c *gin.Context) { */ func (a *Role) Menu(c *gin.Context) { form := &struct { - RoleID uint64 `json:"role_id" form:"role_id" binding:"required"` + RoleID string `json:"role_id" form:"role_id" binding:"required"` }{} if err := bind(form)(c); err != nil { APIFailure(err.(error))(c) return } - data, err := role.NewMenu()(getSession()(c).(*service.Session)).List(form.RoleID) + obj := new(IDStringForm) + obj.ID = form.RoleID + data, err := role.NewMenu()(getSession()(c).(*service.Session)).List(obj.Convert()) APIResponse(err, data)(c) } @@ -178,21 +182,22 @@ func (a *Role) Menu(c *gin.Context) { */ func (a *Role) MenuBind(c *gin.Context) { form := &struct { - RoleID uint64 `json:"role_id" form:"role_id" binding:"required"` + RoleID string `json:"role_id" form:"role_id" binding:"required"` MenuIDs []string `json:"menu_ids" form:"menu_ids" binding:"required"` }{} if err := bind(form)(c); err != nil { APIFailure(err.(error))(c) return } - menuIDs := make([]uint64, 0) - handle := new(IDStringForm) + handle.ID = form.RoleID + roleID := handle.Convert() + menuIDs := make([]uint64, 0) for _, v := range form.MenuIDs { handle.ID = v menuIDs = append(menuIDs, handle.Convert()) } - err := role.NewMenu()(getSession()(c).(*service.Session)).Bind(form.RoleID, menuIDs) + err := role.NewMenu()(getSession()(c).(*service.Session)).Bind(roleID, menuIDs) APIResponse(err)(c) } diff --git a/app/api/websocket.go b/app/api/websocket.go index a87f225..d2bb826 100644 --- a/app/api/websocket.go +++ b/app/api/websocket.go @@ -3,6 +3,8 @@ package api import ( "ArmedPolice/app/handle" "ArmedPolice/app/service" + "ArmedPolice/config" + "errors" "github.com/gin-gonic/gin" "github.com/gorilla/websocket" "net/http" @@ -25,8 +27,18 @@ func (*Websocket) Ws(c *gin.Context) { APIFailure(err)(c) return } - session := getSession()(c).(*service.Session) + token := c.Query(config.APIRequestToken) + if token == "" { + APIFailure(errors.New("Token异常"))(c) + return + } + session := new(service.Session) + + if session, err = service.NewAuthToken(token).Auth(); err != nil { + APIFailure(err)(c) + return + } client := service.NewWebsocket(session.UIDToString(), conn) service.HubMessage.RegisterHandle(client) go client.Write() diff --git a/app/api/work.go b/app/api/work.go index 3de9ee9..78f0940 100644 --- a/app/api/work.go +++ b/app/api/work.go @@ -12,6 +12,9 @@ import ( type Work struct{} +type workLaunchForm struct { +} + /** * @api {post} /api/v1/work/list 工单信息 * @apiVersion 1.0.0 @@ -76,7 +79,18 @@ func (*Work) ToDo(c *gin.Context) { } func (*Work) Launch(c *gin.Context) { - + form := &struct { + IDStringForm + Status int `json:"status" form:"status" binding:"required"` + Remark string `json:"remark" form:"remark"` + IsAssist int `json:"is_assist" form:"is_assist"` + }{} + if err := bind(form)(c); err != nil { + APIFailure(err.(error))(c) + return + } + err := work.NewInstance()(getSession()(c).(*service.Session)).Launch() + APIResponse(err) } func (*Work) Examine(c *gin.Context) { diff --git a/app/common/model/model.go b/app/common/model/model.go index 24dc193..69e0f33 100644 --- a/app/common/model/model.go +++ b/app/common/model/model.go @@ -12,6 +12,7 @@ import ( // IModel type IModel interface { + SetID(id uint64) GetID() uint64 GetEncodeID() string TableName() string @@ -60,6 +61,10 @@ const ( FieldsForDeleted string = "is_deleted" ) +func (m *Model) SetID(id uint64) { + m.ID = id +} + func (m *Model) GetID() uint64 { return m.ID } diff --git a/app/controller/menu/instance.go b/app/controller/menu/instance.go index 85aed3a..61bd3d6 100644 --- a/app/controller/menu/instance.go +++ b/app/controller/menu/instance.go @@ -15,6 +15,7 @@ type InstanceHandle func(session *service.Session) *Instance type ( // InstanceInfo 菜单信息 InstanceInfo struct { + ID string `json:"id"` *model2.SysMenu Children []*InstanceInfo `json:"children"` } @@ -42,6 +43,7 @@ func (c *Instance) tree(src []*model2.SysMenu, parentID uint64) []*InstanceInfo for _, v := range src { if v.ParentID == parentID { out = append(out, &InstanceInfo{ + ID: v.GetEncodeID(), SysMenu: v, Children: c.tree(src, v.ID), }) @@ -51,15 +53,17 @@ func (c *Instance) tree(src []*model2.SysMenu, parentID uint64) []*InstanceInfo } // TreeIdentity 树状筛选 -func TreeIdentity(src []*model.SysMenuScene, parentID uint64) []*InstanceIdentityInfo { +func TreeIdentity(iModel model2.IModel, src []*model.SysMenuScene, parentID uint64) []*InstanceIdentityInfo { out := make([]*InstanceIdentityInfo, 0) for _, v := range src { if v.ParentID == parentID { + iModel.SetID(v.ID) out = append(out, &InstanceIdentityInfo{ + ID: iModel.GetEncodeID(), SysMenuBasic: v.SysMenuBasic, Checked: v.SceneID > 0, - Children: TreeIdentity(src, v.ID), + Children: TreeIdentity(iModel, src, v.ID), }) } } diff --git a/app/controller/role/menu.go b/app/controller/role/menu.go index 3a18ec8..da4d694 100644 --- a/app/controller/role/menu.go +++ b/app/controller/role/menu.go @@ -22,7 +22,7 @@ func (c *Menu) List(roleID uint64) ([]*menu.InstanceIdentityInfo, error) { if err != nil { return nil, err } - return menu.TreeIdentity(out, 0), nil + return menu.TreeIdentity(mSysMenu.SysMenu, out, 0), nil } // Bind 绑定菜单 diff --git a/app/controller/user/menu.go b/app/controller/user/menu.go index 159b1dc..b568c6c 100644 --- a/app/controller/user/menu.go +++ b/app/controller/user/menu.go @@ -27,7 +27,7 @@ func (c *Menu) Menu() ([]*menu.InstanceIdentityInfo, error) { return nil, err } RETURN: - return menu.TreeIdentity(out, 0), nil + return menu.TreeIdentity(mSysMenu.SysMenu, out, 0), nil } func NewMenu() MenuHandle { diff --git a/app/controller/work/instance.go b/app/controller/work/instance.go index 02d1bd4..28fea62 100644 --- a/app/controller/work/instance.go +++ b/app/controller/work/instance.go @@ -54,7 +54,8 @@ func (c *Instance) ToDo() { } -func (c *Instance) Form() error { +// Launch 发起工单申请 +func (c *Instance) Launch() error { return nil } diff --git a/app/controller/work/person.go b/app/controller/work/person.go index dc10e37..892f8c9 100644 --- a/app/controller/work/person.go +++ b/app/controller/work/person.go @@ -3,12 +3,12 @@ package work import ( model2 "ArmedPolice/app/common/model" "ArmedPolice/app/controller/basic" + "ArmedPolice/app/handle" "ArmedPolice/app/model" "ArmedPolice/app/service" "ArmedPolice/serve/orm" "ArmedPolice/utils" "errors" - "fmt" "gorm.io/gorm" "time" ) @@ -95,9 +95,12 @@ func (c *Person) Examine(id uint64, status int, remark string, isAssist int) err } // 推送通知 go utils.TryCatch(func() { - for _, u := range newNextScheduleInfo.Reviewer { + for _, v := range newNextScheduleInfo.Reviewer { // Socket通知 - fmt.Println(u) + service.HubMessage.EmitHandle(&service.HubEmit{ + ID: v, + Msg: handle.NewWorkNotice("你有一条待办事项"), + }) } }) FINISH: diff --git a/app/service/auth.go b/app/service/auth.go new file mode 100644 index 0000000..fe1fcdc --- /dev/null +++ b/app/service/auth.go @@ -0,0 +1,47 @@ +package service + +import ( + "ArmedPolice/config" + cache2 "ArmedPolice/serve/cache" + "ArmedPolice/utils" + "errors" + "fmt" + "time" +) + +type AuthToken struct { + Token string `json:"token"` +} + +func (this *AuthToken) Auth() (*Session, error) { + tokenInfo := utils.JWTDecrypt(this.Token) + + if tokenInfo == nil || len(tokenInfo) <= 0 { + return nil, errors.New("Token无效") + } + expTimestamp := utils.StringToInt64(fmt.Sprintf("%v", tokenInfo["exp"])) + expTime := time.Unix(expTimestamp, 0) + ok := expTime.After(time.Now()) + + if !ok { + return nil, errors.New("Token过期") + } + cache, _ := cache2.Cache.HGet(config.RedisKeyForAccount, fmt.Sprintf("%v", tokenInfo[config.TokenForUID])) + + if cache == "" { + return nil, errors.New("用户未登录或已退出") + } + session := new(Session) + _ = session.UnmarshalBinary([]byte(cache)) + + if !config.SettingInfo.MultipleLogin && session.Token != this.Token { + return nil, errors.New("登录失效,已在其他地方登录!") + } + return session, nil +} + +func NewAuthToken(token string) *AuthToken { + return &AuthToken{ + Token: token, + } +} diff --git a/app/service/websocket.go b/app/service/websocket.go index 3d0cad8..d2b54d0 100644 --- a/app/service/websocket.go +++ b/app/service/websocket.go @@ -40,7 +40,12 @@ func (this *Hub) Run() { } case message := <-this.broadcast: for _, client := range this.clients { - client.send <- message.ToBytes() + select { + case client.send <- message.ToBytes(): + default: + close(client.send) + delete(this.clients, client.ID) + } } case iMsg := <-this.emit: client, has := this.clients[iMsg.ID] diff --git a/router/auth.go b/router/auth.go index b8dad05..7554436 100644 --- a/router/auth.go +++ b/router/auth.go @@ -3,13 +3,9 @@ package router import ( "ArmedPolice/app/service" "ArmedPolice/config" - cache2 "ArmedPolice/serve/cache" "ArmedPolice/utils" - "fmt" - "net/http" - "time" - "github.com/gin-gonic/gin" + "net/http" ) // SkipperURL 跳过验证 @@ -40,34 +36,10 @@ func NeedLogin(skipperURL ...SkipperURL) gin.HandlerFunc { c.Abort() return } - tokenInfo := utils.JWTDecrypt(token) + session, err := service.NewAuthToken(token).Auth() - if tokenInfo == nil || len(tokenInfo) <= 0 { - c.JSON(http.StatusUnauthorized, gin.H{"message": "Token无效"}) - c.Abort() - return - } - expTimestamp := utils.StringToInt64(fmt.Sprintf("%v", tokenInfo["exp"])) - expTime := time.Unix(expTimestamp, 0) - ok := expTime.After(time.Now()) - - if !ok { - c.JSON(http.StatusUnauthorized, gin.H{"message": "Token过期"}) - c.Abort() - return - } - cache, _ := cache2.Cache.HGet(config.RedisKeyForAccount, fmt.Sprintf("%v", tokenInfo[config.TokenForUID])) - - if cache == "" { - c.JSON(http.StatusUnauthorized, gin.H{"message": "用户未登录或已退出"}) - c.Abort() - return - } - session := new(service.Session) - _ = session.UnmarshalBinary([]byte(cache)) - - if !config.SettingInfo.MultipleLogin && session.Token != token { - c.JSON(http.StatusUnauthorized, gin.H{"message": "登录失效,已在其他地方登录!"}) + if err != nil { + c.JSON(http.StatusUnauthorized, gin.H{"message": err.Error()}) c.Abort() return } diff --git a/router/router.go b/router/router.go index 1d0ed7e..7cce9b5 100644 --- a/router/router.go +++ b/router/router.go @@ -46,8 +46,9 @@ func (this *Router) registerAPI() { // Websocket socket接口管理 { _api := new(api.Websocket) - v1.GET("/ws", _api.Ws) - v1.GET("/pong", _api.Pong) + this.handler.GET("/ws", _api.Ws) + this.handler.GET("/pong", _api.Pong) + this.handler.GET("/publish", _api.Publish) } // Captcha 验证码接口管理 v1.GET("/captcha", new(api.Captcha).Captcha) @@ -68,6 +69,8 @@ func (this *Router) registerAPI() { configV1.POST("/edit", _api.Edit) configV1.GET("/area", _api.Area) configV1.POST("/breakdown", _api.Breakdown) + configV1.POST("/breakdown/add", _api.BreakdownAdd) + configV1.POST("/breakdown/edit", _api.BreakdownEdit) } // Tenant 租户单位管理 tenantV1 := v1.Group("/tenant") diff --git a/serve/logger/init.go b/serve/logger/init.go index c7f660e..253ca5a 100644 --- a/serve/logger/init.go +++ b/serve/logger/init.go @@ -42,18 +42,18 @@ func (this *Logger) Load() { func (this *Logger) Init(option *Option) *Logger { this.Option = option - logger = log.New() - logger.SetFormatter(&log.JSONFormatter{TimestampFormat: "2006-01-02 15:04:05"}) - logger.SetReportCaller(true) - logger.AddHook(NewHook(this.File, 0, this.LeastDay)) + _logger := log.New() + _logger.SetFormatter(&log.JSONFormatter{TimestampFormat: "2006-01-02 15:04:05"}) + _logger.SetReportCaller(true) + _logger.AddHook(NewHook(this.File, 0, this.LeastDay)) if this.IsStdout { - logger.SetOutput(io.MultiWriter(os.Stdout)) + _logger.SetOutput(io.MultiWriter(os.Stdout)) } - logger.SetFormatter(formatter(true)) - logger.SetLevel(this.level()) + _logger.SetFormatter(formatter(true)) + _logger.SetLevel(this.level()) - this.Logger = logger + this.Logger = _logger return this }