From 153df336b8302d5583fb8968785b4c9395ae7b5b Mon Sep 17 00:00:00 2001 From: henry Date: Thu, 4 Nov 2021 15:15:11 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E5=AE=8C=E5=96=84=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/config.go | 21 +++ app/api/menu.go | 233 +++++++++++++++++++++++++++++ app/api/role.go | 156 +++++++++++++++++++ app/api/user.go | 5 + app/common/model/common.go | 32 ++-- app/controller/basic/struct.go | 6 + app/controller/config/instance.go | 24 +++ app/controller/menu/instance.go | 136 ++++++++++++++++- app/controller/role/instance.go | 72 +++++++-- app/controller/role/menu.go | 65 +++++++- app/controller/tenant/instance.go | 75 +++++++++- app/controller/user/menu.go | 27 ++-- app/model/sys_menu.go | 75 ++++++++++ app/model/sys_role.go | 4 - cmd/ctl/command/controller/file.go | 2 +- config/config.go | 11 +- config/const.go | 2 - router/router.go | 28 +++- 18 files changed, 898 insertions(+), 76 deletions(-) create mode 100644 app/api/config.go create mode 100644 app/api/role.go create mode 100644 app/controller/config/instance.go diff --git a/app/api/config.go b/app/api/config.go new file mode 100644 index 0000000..712f008 --- /dev/null +++ b/app/api/config.go @@ -0,0 +1,21 @@ +package api + +import ( + "ArmedPolice/app/controller/config" + "ArmedPolice/app/service" + "github.com/gin-gonic/gin" +) + +type Config struct{} + +func (*Config) Area(c *gin.Context) { + form := &struct { + Key string `json:"key" form:"key"` + }{} + if err := bind(form)(c); err != nil { + APIFailure(err.(error))(c) + return + } + data := config.NewInstance()(getSession()(c).(*service.Session)).Area(form.Key) + APIResponse(nil, data) +} diff --git a/app/api/menu.go b/app/api/menu.go index 055c262..cd0a6be 100644 --- a/app/api/menu.go +++ b/app/api/menu.go @@ -1,3 +1,236 @@ package api +import ( + "ArmedPolice/app/controller/menu" + "ArmedPolice/app/service" + + "github.com/gin-gonic/gin" +) + type Menu struct{} + +type ( + // menuForm 菜单信息 + menuForm struct { + ParentID uint64 `json:"parent_id" form:"parent_id"` + Name string `json:"name" form:"name" binding:"required"` + Kind int `json:"kind" form:"kind" binding:"required"` + Link string `json:"link" form:"link"` + Component string `json:"component" form:"component"` + Icon string `json:"icon" form:"icon"` + Auth int `json:"auth" form:"auth"` + Sort int `json:"sort" form:"sort"` + Status int `json:"status" form:"status"` + Remark string `json:"remark" form:"remark"` + } +) + +/** + * @apiDefine Menu 菜单管理 + */ + +/** + * @api {get} /api/v1/menu/list 菜单列表 + * @apiVersion 1.0.0 + * @apiName MenuList + * @apiGroup Menu + * + * @apiHeader {string} x-token token + * + * @apiSuccess (200) {Number} code 成功响应状态码! + * @apiSuccess (200) {String} msg 成功提示 + * @apiSuccess (200) {Array} data 具体信息 + * @apiSuccess (200) {Number} data.id 菜单ID + * @apiSuccess (200) {Number} data.parent_id 父级ID + * @apiSuccess (200) {String} data.name 菜单名称 + * @apiSuccess (200) {Number} data.kind 类型(1:目录,2:菜单) + * @apiSuccess (200) {String} data.link 访问地址 + * @apiSuccess (200) {String} data.component 组件 + * @apiSuccess (200) {Array} data.children="[]" 子集 + * + * @apiSuccessExample {json} Success response: + * HTTPS 200 OK + * { + * "code": 200 + * "msg": "ok" + * "data": [ + * "id": 1, + * "parent_id": 0, + * "name": "系统管理", + * "kind": 1, + * "link": "1" + * "component": "" + * "children": [ + * { + * "id": 2, + * "parent_id": 1, + * "name": "用户管理", + * "kind": 1, + * "link": "1" + * "component": "" + * "children": [], + * } + * ] + * ] + * } + */ +func (a *Menu) List(c *gin.Context) { + data, err := menu.NewInstance()(getSession()(c).(*service.Session)).List() + APIResponse(err, data)(c) +} + +/** + * @api {post} /api/v1/menu/add 菜单添加 + * @apiVersion 1.0.0 + * @apiName MenuAdd + * @apiGroup Menu + * + * @apiHeader {string} x-token token + * + * @apiParam {Number} parent_id 父级ID + * @apiParam {String} name 菜单名 + * @apiParam {Number} kind 菜单类型(1:目录,2:菜单) + * @apiParam {String} link 访问地址 + * @apiParam {String} component 页面组件 + * @apiParam {String} icon 页面icon + * @apiParam {Number} auth 菜单权限(0:普通权限,1:超管权限) + * @apiParam {Number} sort 排序,从大到小 + * @apiParam {Number} status 忘了干嘛,没用 + * @apiParam {String} remark 备注信息 + * + * @apiSuccess (200) {Number} code 成功响应状态码! + * @apiSuccess (200) {String} msg 成功提示 + * + * @apiSuccessExample {json} Success response: + * HTTPS 200 OK + * { + * "code": 200 + * "msg": "ok" + * } + */ +func (a *Menu) Add(c *gin.Context) { + form := new(menuForm) + + if err := bind(form)(c); err != nil { + APIFailure(err.(error))(c) + return + } + err := menu.NewInstance()(getSession()(c).(*service.Session)).Form(&menu.InstanceParams{ + ParentID: form.ParentID, Name: form.Name, Kind: form.Kind, Link: form.Link, Component: form.Component, + Icon: form.Icon, Auth: form.Auth, Sort: form.Sort, Status: form.Status, Remark: form.Remark, + }) + APIResponse(err)(c) +} + +/** + * @api {post} /api/v1/menu/edit 菜单修改 + * @apiVersion 1.0.0 + * @apiName MenuEdit + * @apiGroup Menu + * + * @apiHeader {string} x-token token + * + * @apiParam {Number} id ID + * @apiParam {Number} parent_id 父级ID + * @apiParam {String} name 菜单名 + * @apiParam {Number} kind 菜单类型(1:目录,2:菜单) + * @apiParam {String} link 访问地址 + * @apiParam {String} component 页面组件 + * @apiParam {String} icon 页面icon + * @apiParam {Number} auth 菜单权限(0:普通权限,1:超管权限) + * @apiParam {Number} sort 排序,从大到小 + * @apiParam {Number} status 禁用状态(1:启用,2:禁用) + * @apiParam {String} remark 备注信息 + * + * @apiSuccess (200) {Number} code 成功响应状态码! + * @apiSuccess (200) {String} msg 成功提示 + * + * @apiSuccessExample {json} Success response: + * HTTPS 200 OK + * { + * "code": 200 + * "msg": "ok" + * } + */ +func (a *Menu) Edit(c *gin.Context) { + form := &struct { + IDStringForm + menuForm + }{} + if err := bind(form)(c); err != nil { + APIFailure(err.(error))(c) + return + } + err := menu.NewInstance()(getSession()(c).(*service.Session)).Form(&menu.InstanceParams{ + ID: form.Convert(), ParentID: form.ParentID, Name: form.Name, Kind: form.Kind, Link: form.Link, Component: form.Component, + Icon: form.Icon, Auth: form.Auth, Sort: form.Sort, Status: form.Status, Remark: form.Remark, + }) + APIResponse(err)(c) +} + +/** + * @api {post} /api/v1/menu/status 菜单状态 + * @apiVersion 1.0.0 + * @apiName MenuStatus + * @apiGroup Menu + * + * @apiHeader {string} x-token token + * + * @apiParam {Number} id ID + * @apiParam {Number} status 状态(1:启动,2:禁用) + * + * @apiSuccess (200) {Number} code=200 成功响应状态码! + * @apiSuccess (200) {String} msg="ok" 成功提示 + * + * @apiSuccessExample {json} Success response: + * HTTPS 200 OK + * { + * "code": 200 + * "msg": "ok" + * "data": null + * } + */ +func (a *Menu) Status(c *gin.Context) { + form := &struct { + IDStringForm + Status int `json:"status" form:"status" binding:"required"` + }{} + if err := bind(form)(c); err != nil { + APIFailure(err.(error))(c) + return + } + err := menu.NewInstance()(getSession()(c).(*service.Session)).Status(form.Convert(), form.Status) + APIResponse(err)(c) +} + +/** + * @api {post} /api/v1/menu/delete 删除菜单 + * @apiVersion 1.0.0 + * @apiName MenuDelete + * @apiGroup Menu + * + * @apiHeader {string} x-token token + * + * @apiParam {Number} id ID + * + * @apiSuccess (200) {Number} code=200 成功响应状态码! + * @apiSuccess (200) {String} msg="ok" 成功提示 + * + * @apiSuccessExample {json} Success response: + * HTTPS 200 OK + * { + * "code": 200 + * "msg": "ok" + * "data": null + * } + */ +func (a *Menu) Delete(c *gin.Context) { + form := new(IDStringForm) + + if err := bind(form)(c); err != nil { + APIFailure(err.(error))(c) + return + } + err := menu.NewInstance()(getSession()(c).(*service.Session)).Delete(form.Convert()) + APIResponse(err)(c) +} diff --git a/app/api/role.go b/app/api/role.go new file mode 100644 index 0000000..c6bd3b8 --- /dev/null +++ b/app/api/role.go @@ -0,0 +1,156 @@ +package api + +import ( + "ArmedPolice/app/controller/role" + "ArmedPolice/app/service" + "github.com/gin-gonic/gin" +) + +type Role struct{} + +type roleForm struct { + ParentID uint64 `json:"parent_id" form:"parent_id"` + Name string `json:"name" form:"name" binding:"required"` + Remark string `json:"remark" form:"remark" binding:"required"` + Sort int `json:"sort" form:"sort"` +} + +/** + * @apiDefine Role 菜单管理 + */ + +func (*Role) List(c *gin.Context) { + data, err := role.NewInstance()(getSession()(c).(*service.Session)).List() + APIResponse(err, data)(c) +} + +func (a *Role) Add(c *gin.Context) { + form := new(roleForm) + + if err := bind(form)(c); err != nil { + APIFailure(err.(error))(c) + return + } + err := role.NewInstance()(getSession()(c).(*service.Session)).Form(&role.InstanceParams{ + ParentID: form.ParentID, Name: form.Name, Remark: form.Remark, Sort: form.Sort, + }) + APIResponse(err)(c) +} + +func (a *Role) Edit(c *gin.Context) { + form := &struct { + IDStringForm + roleForm + }{} + if err := bind(form)(c); err != nil { + APIFailure(err.(error))(c) + return + } + err := role.NewInstance()(getSession()(c).(*service.Session)).Form(&role.InstanceParams{ + ID: form.Convert(), ParentID: form.ParentID, Name: form.Name, Remark: form.Remark, Sort: form.Sort, + }) + APIResponse(err)(c) +} + +func (a *Role) Delete(c *gin.Context) { + form := new(IDStringForm) + + if err := bind(form)(c); err != nil { + APIFailure(err.(error))(c) + return + } + err := role.NewInstance()(getSession()(c).(*service.Session)).Delete(form.Convert()) + APIResponse(err)(c) +} + +/** + * @api {post} /api/v1/role/menu 菜单信息 + * @apiVersion 1.0.0 + * @apiName RoleMenu + * @apiGroup Role + * + * @apiHeader {string} x-token token + * + * @apiSuccess (200) {Number} code 成功响应状态码! + * @apiSuccess (200) {String} msg 成功提示 + * @apiSuccess (200) {Array} data 具体信息 + * @apiSuccess (200) {Number} data.id 菜单ID + * @apiSuccess (200) {Number} data.parent_id 父级ID + * @apiSuccess (200) {String} data.name 菜单名称 + * @apiSuccess (200) {Number} data.kind 类型(1:目录,2:菜单) + * @apiSuccess (200) {String} data.link 访问地址 + * @apiSuccess (200) {String} data.component 组件 + * @apiSuccess (200) {Array} data.children="[]" 子集 + * + * @apiSuccessExample {json} Success response: + * HTTPS 200 OK + * { + * "code": 200 + * "msg": "ok" + * "data": [ + * "id": 1, + * "parent_id": 0, + * "name": "系统管理", + * "kind": 1, + * "link": "1" + * "component": "" + * "children": [ + * { + * "id": 2, + * "parent_id": 1, + * "name": "用户管理", + * "kind": 1, + * "link": "1" + * "component": "" + * "children": [], + * } + * ] + * ] + * } + */ +func (a *Role) Menu(c *gin.Context) { + form := &struct { + RoleID uint64 `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) + APIResponse(err, data)(c) +} + +/** + * @api {post} /api/v1/role/menu/bind 菜单绑定 + * @apiVersion 1.0.0 + * @apiName RoleMenuBind + * @apiGroup Role + * + * @apiHeader {string} x-token token + * + * @apiParam {Number} role_id 角色ID + * @apiParam {Array.Number} menu_ids 菜单ID + * + * @apiSuccess (200) {Number} code=200 成功响应状态码! + * @apiSuccess (200) {String} msg="ok" 成功提示 + * + * @apiSuccessExample {json} Success response: + * HTTPS 200 OK + * { + * "code": 200 + * "msg": "ok" + * "data": null + * } + */ +func (a *Role) MenuBind(c *gin.Context) { + form := &struct { + RoleID uint64 `json:"role_id" form:"role_id" binding:"required"` + MenuIDs []uint64 `json:"menu_ids" form:"menu_ids" binding:"required"` + }{} + if err := bind(form)(c); err != nil { + APIFailure(err.(error))(c) + return + } + err := role.NewMenu()(getSession()(c).(*service.Session)).Bind(form.RoleID, form.MenuIDs) + APIResponse(err)(c) +} diff --git a/app/api/user.go b/app/api/user.go index 3ac58f2..6260063 100644 --- a/app/api/user.go +++ b/app/api/user.go @@ -13,6 +13,11 @@ func (*User) Info(c *gin.Context) { APIResponse(nil, data) } +func (*User) Menu(c *gin.Context) { + data, err := user.NewMenu()(getSession()(c).(*service.Session)).Menu() + APIResponse(err, data) +} + func (*User) List(c *gin.Context) { form := &struct { Name string `json:"name" form:"name"` diff --git a/app/common/model/common.go b/app/common/model/common.go index 94dd486..8a1b5f9 100644 --- a/app/common/model/common.go +++ b/app/common/model/common.go @@ -3,7 +3,6 @@ package model import ( "ArmedPolice/config" "ArmedPolice/utils" - "strings" ) type Gender struct { @@ -60,21 +59,26 @@ type Area struct { Address string `gorm:"column:address;type:varchar(255);default:null;comment:详细地址" json:"address"` } -func (m *Area) FormatBasic() string { - address := make([]string, 0) - address = append(address, config.SettingAreaInfo[config.DefaultChinaAreaCode][m.Province]) - - if m.City != "" { - address = append(address, config.SettingAreaInfo[m.Province][m.City]) - } - if m.District != "" { - address = append(address, config.SettingAreaInfo[m.City][m.District]) - } - return strings.Join(address, "-") +type AreaInfo struct { + Province string `json:"province"` + City string `json:"city"` + District string `json:"district"` + Address string `json:"address"` } -func (m *Area) FormatDetail() string { - return m.FormatBasic() + ";" + m.Address +func (m *Area) Format() *AreaInfo { + out := &AreaInfo{Address: m.Address} + + if m.Province != "" { + out.Province = config.SettingAreaInfo[config.DefaultChinaAreaCode][m.Province] + } + if m.City != "" { + out.City = config.SettingAreaInfo[m.Province][m.City] + } + if m.District != "" { + out.District = config.SettingAreaInfo[m.City][m.District] + } + return out } // Position 坐标信息 diff --git a/app/controller/basic/struct.go b/app/controller/basic/struct.go index 853ee8c..180ff04 100644 --- a/app/controller/basic/struct.go +++ b/app/controller/basic/struct.go @@ -10,4 +10,10 @@ type ( CommonIDString struct { ID string `json:"id"` } + CommonArea struct { + Province string `json:"province"` + City string `json:"city"` + District string `json:"district"` + Address string `json:"address"` + } ) diff --git a/app/controller/config/instance.go b/app/controller/config/instance.go new file mode 100644 index 0000000..ec8a07f --- /dev/null +++ b/app/controller/config/instance.go @@ -0,0 +1,24 @@ +package config + +import ( + "ArmedPolice/app/service" + "ArmedPolice/config" +) + +type Instance struct{ *service.Session } + +type InstanceHandle func(session *service.Session) *Instance + +// Area 区域信息 +func (c *Instance) Area(key string) map[string]string { + if key == "" { + key = config.DefaultChinaAreaCode + } + return config.SettingAreaInfo[key] +} + +func NewInstance() InstanceHandle { + return func(session *service.Session) *Instance { + return &Instance{session} + } +} diff --git a/app/controller/menu/instance.go b/app/controller/menu/instance.go index 2892959..85aed3a 100644 --- a/app/controller/menu/instance.go +++ b/app/controller/menu/instance.go @@ -1,23 +1,149 @@ package menu import ( - "ArmedPolice/app/controller/basic" + model2 "ArmedPolice/app/common/model" + "ArmedPolice/app/model" "ArmedPolice/app/service" + "errors" + "time" ) type Instance struct{ *service.Session } type InstanceHandle func(session *service.Session) *Instance -func (c *Instance) List() (*basic.ReturnPages, error) { - return &basic.ReturnPages{Data: nil, Count: 0}, nil +type ( + // InstanceInfo 菜单信息 + InstanceInfo struct { + *model2.SysMenu + Children []*InstanceInfo `json:"children"` + } + // InstanceIdentityInfo 多个身份菜单信息 + InstanceIdentityInfo struct { + ID string `json:"id"` + *model2.SysMenuBasic + Checked bool `json:"checked"` + Children []*InstanceIdentityInfo `json:"children"` + } + // InstanceParams 菜单参数 + InstanceParams struct { + ID, ParentID uint64 + Kind, Auth int + Name, Link, Component, Icon string + Sort, Status int + Remark string + } +) + +// tree 树状筛选 +func (c *Instance) tree(src []*model2.SysMenu, parentID uint64) []*InstanceInfo { + out := make([]*InstanceInfo, 0) + + for _, v := range src { + if v.ParentID == parentID { + out = append(out, &InstanceInfo{ + SysMenu: v, + Children: c.tree(src, v.ID), + }) + } + } + return out } -func (c *Instance) Form() error { +// TreeIdentity 树状筛选 +func TreeIdentity(src []*model.SysMenuScene, parentID uint64) []*InstanceIdentityInfo { + out := make([]*InstanceIdentityInfo, 0) + + for _, v := range src { + if v.ParentID == parentID { + out = append(out, &InstanceIdentityInfo{ + SysMenuBasic: v.SysMenuBasic, + Checked: v.SceneID > 0, + Children: TreeIdentity(src, v.ID), + }) + } + } + return out +} + +// List 列表信息 +func (c *Instance) List() ([]*InstanceInfo, error) { + mSysMenu := model.NewSysMenu() + + out, err := mSysMenu.Menus() + + if err != nil { + return nil, err + } + return c.tree(out, 0), nil +} + +// Form 数据操作 +func (c *Instance) Form(params *InstanceParams) error { + if params.ID <= 0 { + return model2.Create(&model2.SysMenu{ + SysMenuBasic: model2.SysMenuBasic{ + ParentID: params.ParentID, + Name: params.Name, + Kind: model2.SysMenuKind(params.Kind), + Link: params.Link, + Component: params.Component, + Icon: params.Icon, + }, + Auth: model2.SysMenuAuth(params.Auth), + Sort: params.Sort, + Status: model2.SysMenuStatusForNormal, + Remark: params.Remark, + }) + } + out := model.NewSysMenu() + out.ID = params.ID + + isExist, err := model2.FirstWhere(out.SysMenu) + + if err != nil { + return err + } else if !isExist { + return errors.New("菜单信息不存在") + } + out.ParentID = params.ParentID + out.Name = params.Name + out.Kind = model2.SysMenuKind(params.Kind) + out.Link = params.Link + out.Component = params.Component + out.Icon = params.Icon + out.Auth = model2.SysMenuAuth(params.Auth) + out.Sort = params.Sort + out.Status = model2.SysMenuStatus(params.Status) + out.Remark = params.Remark + + if err = model2.Save(out); err != nil { + return err + } return nil } -func (c *Instance) Delete() error { +// Status 状态操作 +func (c *Instance) Status(id uint64, status int) error { + mSysMenu := model.NewSysMenu() + mSysMenu.ID = id + + if err := model2.Updates(mSysMenu.SysMenu, map[string]interface{}{ + "status": status, "updated_at": time.Now(), + }); err != nil { + return err + } + return nil +} + +// Delete 删除操作 +func (c *Instance) Delete(id uint64) error { + mSysMenu := model.NewSysMenu() + mSysMenu.ID = id + + if err := model2.Delete(mSysMenu.SysMenu); err != nil { + return err + } return nil } diff --git a/app/controller/role/instance.go b/app/controller/role/instance.go index d207d88..793acc9 100644 --- a/app/controller/role/instance.go +++ b/app/controller/role/instance.go @@ -2,7 +2,6 @@ package role import ( model2 "ArmedPolice/app/common/model" - "ArmedPolice/app/controller/basic" "ArmedPolice/app/model" "ArmedPolice/app/service" ) @@ -11,29 +10,76 @@ type Instance struct{ *service.Session } type InstanceHandle func(session *service.Session) *Instance -func (c *Instance) List() (*basic.PageDataResponse, error) { +type ( + // InstanceInfo 基本信息 + InstanceInfo struct { + ID string `json:"id"` + Name string `json:"name"` + Children []*InstanceInfo `json:"children"` + } + // InstanceParams 参数信息 + InstanceParams struct { + ID, ParentID uint64 + Name, Remark string + Sort int + } +) + +func (c *Instance) tree(src []*model2.SysRole, parentID uint64) []*InstanceInfo { + out := make([]*InstanceInfo, 0) + + for _, v := range src { + if v.ParentID == parentID { + out = append(out, &InstanceInfo{ + ID: v.GetEncodeID(), + Name: v.Name, + Children: c.tree(src, v.ID), + }) + } + } + return out +} + +// List 列表信息 +func (c *Instance) List() ([]*InstanceInfo, error) { mSysRole := model.NewSysRole() - where := make([]*model2.ModelWhereOrder, 0) - - //if { - // - //} + where := []*model2.ModelWhereOrder{ + &model2.ModelWhereOrder{ + Order: model2.NewOrder("sort", model2.OrderModeToDesc), + }, + } out := make([]*model2.SysRole, 0) if err := model2.Find(mSysRole.SysRole, &out, where...); err != nil { return nil, err } - - return &basic.PageDataResponse{Data: nil, Count: 0}, nil + return c.tree(out, 0), nil } -func (c *Instance) Form() error { - return nil +// Form 数据处理 +func (c *Instance) Form(params *InstanceParams) error { + mSysRole := model.NewSysRole() + + if params.ID > 0 { + mSysRole.ID = params.ID + + return model2.Updates(mSysRole.SysRole, map[string]interface{}{ + "parent_id": params.ParentID, "name": params.Name, "remark": params.Remark, "sort": params.Sort, + }) + } + mSysRole.ParentID = params.ParentID + mSysRole.Name = params.Name + mSysRole.Remark = params.Remark + mSysRole.Sort = params.Sort + return model2.Create(mSysRole.SysRole) } -func (c *Instance) Delete() error { - return nil +// Delete 删除操作 +func (c *Instance) Delete(id uint64) error { + mSysRole := model.NewSysRole() + mSysRole.ID = id + return model2.Delete(mSysRole.SysRole) } func NewInstance() InstanceHandle { diff --git a/app/controller/role/menu.go b/app/controller/role/menu.go index 6aae74f..3a18ec8 100644 --- a/app/controller/role/menu.go +++ b/app/controller/role/menu.go @@ -1,24 +1,73 @@ package role import ( - "ArmedPolice/app/controller/basic" + model2 "ArmedPolice/app/common/model" + "ArmedPolice/app/controller/menu" + "ArmedPolice/app/model" "ArmedPolice/app/service" + "ArmedPolice/serve/orm" + "errors" + "gorm.io/gorm" ) type Menu struct{ *service.Session } type MenuHandle func(session *service.Session) *Menu -func (c *Menu) List() (*basic.PageDataResponse, error) { - return &basic.PageDataResponse{Data: nil, Count: 0}, nil +// List 菜单列表 +func (c *Menu) List(roleID uint64) ([]*menu.InstanceIdentityInfo, error) { + mSysMenu := model.NewSysMenu() + out, err := mSysMenu.RoleMenu(roleID) + + if err != nil { + return nil, err + } + return menu.TreeIdentity(out, 0), nil } -func (c *Menu) Form() error { - return nil -} +// Bind 绑定菜单 +func (c *Menu) Bind(roleID uint64, menuIDs []uint64) error { + if len(menuIDs) > 0 { + var count int64 -func (c *Menu) Delete() error { - return nil + mSysMenu := model.NewSysMenu() + + if err := model2.Count(mSysMenu.SysMenu, &count, model2.NewWhereIn("id", menuIDs), + model2.NewWhere("auth", model2.SysMenuAuthForSystem)); err != nil { + return err + } else if count > 0 { + return errors.New("不可设置超管菜单") + } + } + mSysRoleMenu := model.NewSysRoleMenu() + + return orm.GetDB().Transaction(func(tx *gorm.DB) error { + err := model2.DeleteWhere(mSysRoleMenu.SysRoleMenu, []*model2.ModelWhere{model2.NewWhere("role_id", roleID)}, tx) + + if err != nil { + return err + } + if len(menuIDs) <= 0 { + return nil + } + menus := make([]*model2.SysRoleMenu, 0) + + mark := make(map[uint64]uint64, 0) + + for _, v := range menuIDs { + if _, has := mark[v]; has { + continue + } + menus = append(menus, &model2.SysRoleMenu{ + ModelTenant: model2.ModelTenant{TenantID: c.TenantID}, RoleID: roleID, MenuID: v, + }) + mark[v] = v + } + if err = model2.Creates(mSysRoleMenu.SysRoleMenu, menus, tx); err != nil { + return err + } + return nil + }) } func NewMenu() MenuHandle { diff --git a/app/controller/tenant/instance.go b/app/controller/tenant/instance.go index 0bffc85..0e5fa75 100644 --- a/app/controller/tenant/instance.go +++ b/app/controller/tenant/instance.go @@ -5,31 +5,90 @@ import ( "ArmedPolice/app/controller/basic" "ArmedPolice/app/model" "ArmedPolice/app/service" + "errors" ) type Instance struct{ *service.Session } type InstanceHandle func(session *service.Session) *Instance -func (c *Instance) List(name string, page, pageSize int) (*basic.PageDataResponse, error) { +type ( + // InstanceInfo 租户信息 + InstanceInfo struct { + ID string `json:"id"` + Name string `json:"name"` + *model2.AreaInfo + Children []*InstanceInfo `json:"children"` + } + // InstanceParams 参数信息 + InstanceParams struct { + ID, ParentID uint64 + Name, Remark string + basic.CommonArea + } +) + +func (c *Instance) tree(src []*model2.SysTenant, parentID uint64) []*InstanceInfo { + out := make([]*InstanceInfo, 0) + + for _, v := range src { + if v.ParentID == parentID { + out = append(out, &InstanceInfo{ + ID: v.GetEncodeID(), + Name: v.Name, + AreaInfo: v.Area.Format(), + Children: c.tree(src, v.ID), + }) + } + } + return out +} + +// List 列表信息 +func (c *Instance) List() ([]*InstanceInfo, error) { mSysTenant := model.NewSysTenant() out := make([]*model2.SysTenant, 0) - var count int64 - - if err := model2.Pages(mSysTenant.SysTenant, &out, page, pageSize, &count); err != nil { + if err := model2.Find(mSysTenant.SysTenant, &out); err != nil { return nil, err } - return &basic.PageDataResponse{Data: nil, Count: 0}, nil + return c.tree(out, 0), nil } -func (c *Instance) Form() error { - return nil +// Form 数据操作 +func (c *Instance) Form(params *InstanceParams) error { + mSysTenant := model.NewSysTenant() + + if params.ID > 0 { + mSysTenant.ID = params.ID + + isExist, err := model2.First(mSysTenant.SysTenant) + + if err != nil { + return err + } else if !isExist { + return errors.New("操作错误,数据不存在") + } + } + mSysTenant.ParentID = params.ParentID + mSysTenant.Name = params.Name + mSysTenant.Area = model2.Area{ + Province: params.Province, City: params.City, District: params.District, Address: params.Address, + } + mSysTenant.Remark = params.Remark + + if mSysTenant.ID > 0 { + return model2.Updates(mSysTenant.SysTenant, mSysTenant.SysTenant) + } + return model2.Create(mSysTenant.SysTenant) } +// Delete 删除操作 func (c *Instance) Delete(id uint64) error { - return nil + mSysTenant := model.NewSysTenant() + mSysTenant.ID = id + return model2.Delete(mSysTenant.SysTenant) } func NewInstance() InstanceHandle { diff --git a/app/controller/user/menu.go b/app/controller/user/menu.go index 6aa01e0..159b1dc 100644 --- a/app/controller/user/menu.go +++ b/app/controller/user/menu.go @@ -1,7 +1,8 @@ package user import ( - "ArmedPolice/app/controller/basic" + "ArmedPolice/app/controller/menu" + "ArmedPolice/app/model" "ArmedPolice/app/service" ) @@ -9,16 +10,24 @@ type Menu struct{ *service.Session } type MenuHandle func(session *service.Session) *Menu -func (c *Menu) List() (*basic.PageDataResponse, error) { - return &basic.PageDataResponse{Data: nil, Count: 0}, nil -} +// Menu 用户菜单信息 +func (c *Menu) Menu() ([]*menu.InstanceIdentityInfo, error) { + mSysMenu := model.NewSysMenu() -func (c *Menu) Form() error { - return nil -} + out := make([]*model.SysMenuScene, 0) + var err error -func (c *Menu) Delete() error { - return nil + if c.IsAdmin { + if out, err = mSysMenu.SystemMenu(); err != nil { + return nil, err + } + goto RETURN + } + if out, err = mSysMenu.UserMenu(c.UID); err != nil { + return nil, err + } +RETURN: + return menu.TreeIdentity(out, 0), nil } func NewMenu() MenuHandle { diff --git a/app/model/sys_menu.go b/app/model/sys_menu.go index 6a240d6..6480cc2 100644 --- a/app/model/sys_menu.go +++ b/app/model/sys_menu.go @@ -2,12 +2,87 @@ package model import ( "ArmedPolice/app/common/model" + "ArmedPolice/serve/orm" + "fmt" ) type SysMenu struct { *model.SysMenu } +type SysMenuScene struct { + ID uint64 `json:"id"` + *model.SysMenuBasic + SceneID uint64 `json:"scene_id"` // 场景(租户,角色) +} + +// Menus 菜单信息 +func (m *SysMenu) Menus() ([]*model.SysMenu, error) { + out := make([]*model.SysMenu, 0) + + db := orm.GetDB().Table(m.TableName()). + Where("status = ? AND is_deleted = ?", model.SysMenuStatusForNormal, model.DeleteStatusForNot) + + if err := db.Order("parent_id " + model.OrderModeToAsc).Order("sort " + model.OrderModeToDesc).Scan(&out).Error; err != nil { + return nil, err + } + return out, nil +} + +// SystemMenu 系统菜单 +func (m *SysMenu) SystemMenu() ([]*SysMenuScene, error) { + out := make([]*SysMenuScene, 0) + + db := orm.GetDB().Table(m.TableName()). + Select("id, parent_id, name, kind, link, component, icon, 1 AS scene_id"). + Where("status = ? AND is_deleted = ?", model.SysMenuStatusForNormal, model.DeleteStatusForNot) + + if err := db.Order("parent_id " + model.OrderModeToAsc).Order("sort " + model.OrderModeToDesc).Scan(&out).Error; err != nil { + return nil, err + } + return out, nil +} + +// UserMenu 用户菜单 +func (m *SysMenu) UserMenu(uid uint64) ([]*SysMenuScene, error) { + mSysUserRole := NewSysUserRole() + + mSysRoleMenu := NewSysRoleMenu() + + out := make([]*SysMenuScene, 0) + + db := orm.GetDB().Table(mSysUserRole.TableName()+" AS u_r"). + Select("m.id, m.parent_id, m.name, m.kind, m.link, m.component, m.icon, 1 AS scene_id"). + Joins(fmt.Sprintf("LEFT JOIN %s AS r_m ON u_r.role_id = r_m.id AND r_m.is_deletd = %d", + mSysRoleMenu.TableName(), model.DeleteStatusForNot)). + Joins(fmt.Sprintf("LEFT JOIN %s AS m ON r_m.menu_id = m.id AND m.status = %d AND m.is_deleted = %d", + m.TableName(), model.SysMenuStatusForNormal, model.DeleteStatusForNot)). + Where("u_r.uid = ? AND u_r.is_deleted = ?", uid, model.DeleteStatusForNot) + + if err := db.Order("m.parent_id " + model.OrderModeToAsc).Order("m.sort " + model.OrderModeToDesc).Scan(&out).Error; err != nil { + return nil, err + } + return out, nil +} + +// RoleMenu 角色菜单 +func (m *SysMenu) RoleMenu(roleID uint64) ([]*SysMenuScene, error) { + mSysRoleMenu := NewSysRoleMenu() + + out := make([]*SysMenuScene, 0) + + db := orm.GetDB().Table(m.TableName()+" AS m"). + Select("m.id, m.parent_id, m.name, m.kind, m.link, m.component, m.icon, r_m.id AS scene_id"). + Joins(fmt.Sprintf("LEFT JOIN %s AS r_m ON m.id = r_m.menu_id AND r_m.role_id = %d AND r_m.is_deleted = %d", + mSysRoleMenu.TableName(), roleID, model.DeleteStatusForNot)). + Where("m.status = ? AND m.is_deleted = ?", model.SysMenuStatusForNormal, model.DeleteStatusForNot) + + if err := db.Order("m.parent_id " + model.OrderModeToAsc).Order("m.sort " + model.OrderModeToDesc).Scan(&out).Error; err != nil { + return nil, err + } + return out, nil +} + func NewSysMenu() *SysMenu { return &SysMenu{SysMenu: model.NewSysMenu()} } diff --git a/app/model/sys_role.go b/app/model/sys_role.go index 08cf54c..c436c01 100644 --- a/app/model/sys_role.go +++ b/app/model/sys_role.go @@ -8,10 +8,6 @@ type SysRole struct { *model.SysRole } -func (m *SysRole) Roles() { - -} - func NewSysRole() *SysRole { return &SysRole{SysRole: model.NewSysRole()} } diff --git a/cmd/ctl/command/controller/file.go b/cmd/ctl/command/controller/file.go index 670cdf2..a597735 100644 --- a/cmd/ctl/command/controller/file.go +++ b/cmd/ctl/command/controller/file.go @@ -27,7 +27,7 @@ func (c *{{.StrutName}}) Form() error { return nil } -func (c *{{.StrutName}}) Delete() error { +func (c *{{.StrutName}}) Delete(id uint64) error { return nil } diff --git a/config/config.go b/config/config.go index d182f5a..4c459f6 100644 --- a/config/config.go +++ b/config/config.go @@ -1,9 +1,8 @@ package config var ( - SettingInfo = new(Setting) - RPCServerSettingInfo = new(RPCServerSetting) - SettingAreaInfo = make(map[string]map[string]string, 0) + SettingInfo = new(Setting) + SettingAreaInfo = make(map[string]map[string]string, 0) ) // Mysql 配置 @@ -107,9 +106,3 @@ type Setting struct { Level string `yaml:"level"` } } - -// RPCServerSetting 配置 -type RPCServerSetting struct { - Key int `yaml:"key"` - Servers map[string]*RPCServer `yaml:"servers"` -} diff --git a/config/const.go b/config/const.go index 8c473a7..38cb936 100644 --- a/config/const.go +++ b/config/const.go @@ -14,12 +14,10 @@ const ( const ( TokenForUID string = "uid" TokenForSession string = "session" - TokenForGrade string = "grade" ) const ( APIRequestToken string = "x-token" - APIRequestGrade string = "x-grade" ) const ( diff --git a/router/router.go b/router/router.go index e4befe8..1761fd4 100644 --- a/router/router.go +++ b/router/router.go @@ -42,6 +42,9 @@ func (this *Router) registerAPI() { apiPrefix + "/v1/user/info", }...))) v1 := g.Group("/v1") + + v1.GET("/captcha", new(api.Captcha).Captcha) + v1.POST("/upload", new(api.Upload).Upload) // Account 接口管理 accountV1 := v1.Group("/account") { @@ -49,12 +52,31 @@ func (this *Router) registerAPI() { accountV1.POST("/login", _api.Login) accountV1.POST("/logout", _api.Logout) } + // Menu 菜单管理 + menuV1 := v1.Group("/menu") + { + _api := new(api.Menu) + menuV1.POST("/list", _api.List) + menuV1.POST("/add", _api.Add) + menuV1.POST("/edit", _api.Edit) + menuV1.POST("/status", _api.Status) + menuV1.POST("/delete", _api.Delete) + } // User 用户管理 - UserV1 := v1.Group("/user") + userV1 := v1.Group("/user") { _api := new(api.User) - UserV1.GET("/info", _api.Info) - UserV1.GET("/list", _api.List) + userV1.GET("/info", _api.Info) + userV1.GET("/menu", _api.Menu) + userV1.POST("/list", _api.List) + } + // Role 角色管理 + roleV1 := v1.Group("/role") + { + _api := new(api.User) + roleV1.POST("/list", _api.List) + roleV1.GET("/menu", _api.Menu) + roleV1.GET("/list", _api.List) } }