feat:完善项目

This commit is contained in:
henry
2021-11-08 15:52:46 +08:00
parent 1502076841
commit 1cc95fb5ca
16 changed files with 154 additions and 64 deletions

View File

@ -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) {

View File

@ -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,

View File

@ -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)
}

View File

@ -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()

View File

@ -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) {

View File

@ -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
}

View File

@ -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),
})
}
}

View File

@ -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 绑定菜单

View File

@ -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 {

View File

@ -54,7 +54,8 @@ func (c *Instance) ToDo() {
}
func (c *Instance) Form() error {
// Launch 发起工单申请
func (c *Instance) Launch() error {
return nil
}

View File

@ -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:

47
app/service/auth.go Normal file
View File

@ -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,
}
}

View File

@ -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]

View File

@ -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
}

View File

@ -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")

View File

@ -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
}