添加组织管理

This commit is contained in:
root 2024-08-07 12:45:01 +08:00
parent 41d8c8174b
commit 97faf9126b
21 changed files with 2172 additions and 9 deletions

View File

@ -2,8 +2,10 @@ package initialize
import ( import (
"fmt" "fmt"
"github.com/flipped-aurora/gin-vue-admin/server/global" "github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/email" "github.com/flipped-aurora/gin-vue-admin/server/plugin/email"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/organization"
"github.com/flipped-aurora/gin-vue-admin/server/utils/plugin" "github.com/flipped-aurora/gin-vue-admin/server/utils/plugin"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@ -30,5 +32,6 @@ func bizPluginV1(group ...*gin.RouterGroup) {
global.GVA_CONFIG.Email.Port, global.GVA_CONFIG.Email.Port,
global.GVA_CONFIG.Email.IsSSL, global.GVA_CONFIG.Email.IsSSL,
)) ))
PluginInit(public, organization.CreateOrganizationPlug())
holder(public, private) holder(public, private)
} }

View File

@ -0,0 +1,133 @@
## GVA 组织管理功能
#### 开发者:奇淼
### 本插件支持自动安装
### 图例
![img](https://qmplusimg.henrongyi.top/plugin%2Forganization1.jpg)
![img](https://qmplusimg.henrongyi.top/plugin%2Forganization2.jpg)
![img](https://qmplusimg.henrongyi.top/plugin%2Forganization3.jpg)
![img](https://qmplusimg.henrongyi.top/plugin%2Forganization4.jpg)
![img](https://qmplusimg.henrongyi.top/plugin%2Forganization5.jpg)
### 手动安装方法
1.解压zip获得organization文件夹
2.将 organization/web/plugin/organization 放置在web/plugin下
3.将 organization/server/plugin/organization 放置在server/plugin下
#### 执行如下注册方法
### 注册(手动自动都需要)
#### 1. 前往GVA主程序下的initialize/router.go 在Routers 方法最末尾按照你需要的及安全模式添加本插件
PluginInit(PublicGroup, organization.CreateOrganizationPlug())
到gva系统角色管理分配角色的菜单权限和api权限即可插件会自动注册菜单和api需要手动分配。
### 2. 配置说明
#### 2-1 全局配置结构体说明
无配置
#### 2-2 结构说明
// 组织基础结构
type Organization struct {
global.GVA_MODEL
Name string `json:"name" form:"name" gorm:"column:name;comment:;"`
ParentID uint `json:"parentID" form:"parentID" gorm:"column:parent_id;comment:父节点ID;"`
}
// 组织用户关系表
type OrgUser struct {
Organization Organization `json:"organization"`
OrganizationID uint `json:"organizationID,omitempty" form:"organizationID" `
SysUserID uint `json:"sysUserID,omitempty" form:"sysUserID"`
IsAdmin bool `json:"isAdmin" form:"isAdmin"`
SysUser system.SysUser `json:"sysUser"`
}
// 组织内用户操作结构
type OrgUserReq struct {
OrganizationID uint `json:"organizationID,omitempty"`
ToOrganizationID uint `json:"toOrganizationID,omitempty"`
SysUserIDS []uint `json:"sysUserIDS,omitempty"`
}
// 搜索组织功能(未使用)
type OrganizationSearch struct {
organization.Organization
request.PageInfo
}
// 搜索组织内用户功能
type OrgUserSearch struct {
organization.OrgUser
UserName string `json:"userName" form:"userName"`
request.PageInfo
}
### 3. 方法API
无,后续维护会增加便捷查询当前用户所属组织,所属组织子组织以及成员等便捷方法,根据反馈添加。
### 4. 可直接调用的接口
POST /org/createOrganization // 新建Organization
入参为 Organization 结构体
DELETE /org/deleteOrganization // 删除Organization
入参为 ID int
DELETE /org/deleteOrganizationByIds // 批量删除Organization
入参为 IDS:[]int
PUT /org/updateOrganization // 更新Organization
入参为 Organization 结构体
POST /org/createOrgUser // 人员入职
入参为 OrgUserReq 结构体
PUT /org/setOrgUserAdmin // 管理员设置
入参为 {
sysUserID: 用户id,
isAdmin: 是否管理员 bool
}
GET /org/findOrganization // 根据ID获取Organization
入参为 { ID: 组织id }
GET /org/getOrganizationList // 获取Organization列表
无需入参
GET /org/findOrgUserAll // 获取当前组织下所有用户ID
入参为 { organizationID: 组织id }
GET /org/findOrgUserList // 获取当前组织下所有用户(分页)
入参为 OrgUserSearch 结构体
DELETE /org/deleteOrgUser // 删除当前组织下选中用户
入参为 { sysUserIDS:用户id []int, organizationID: 当前组织id }
PUT /org/transferOrgUser // 用户转移组织
入参为 sysUserIDS: 需要操作的用户的ids []int,
organizationID: 原始组织ID int,
toOrganizationID: 目标组织ID int,

View File

@ -0,0 +1,259 @@
package api
import (
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
organization "github.com/flipped-aurora/gin-vue-admin/server/plugin/organization/model"
organizationReq "github.com/flipped-aurora/gin-vue-admin/server/plugin/organization/model/request"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/organization/service"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
type OrganizationApi struct {
}
var orgService = service.ServiceGroupApp.OrganizationService
// CreateOrganization 创建Organization
// @Tags Organization
// @Summary 创建Organization
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body organization.Organization true "创建Organization"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /org/createOrganization [post]
func (orgApi *OrganizationApi) CreateOrganization(c *gin.Context) {
var org organization.Organization
_ = c.ShouldBindJSON(&org)
if err := orgService.CreateOrganization(org); err != nil {
global.GVA_LOG.Error("创建失败!", zap.Error(err))
response.FailWithMessage("创建失败", c)
} else {
response.OkWithMessage("创建成功", c)
}
}
// DeleteOrganization 删除Organization
// @Tags Organization
// @Summary 删除Organization
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body organization.Organization true "删除Organization"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
// @Router /org/deleteOrganization [delete]
func (orgApi *OrganizationApi) DeleteOrganization(c *gin.Context) {
var org organization.Organization
_ = c.ShouldBindJSON(&org)
if err := orgService.DeleteOrganization(org); err != nil {
global.GVA_LOG.Error("删除失败!", zap.Error(err))
response.FailWithMessage(err.Error(), c)
} else {
response.OkWithMessage("删除成功", c)
}
}
// DeleteOrganizationByIds 批量删除Organization
// @Tags Organization
// @Summary 批量删除Organization
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.IdsReq true "批量删除Organization"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"批量删除成功"}"
// @Router /org/deleteOrganizationByIds [delete]
func (orgApi *OrganizationApi) DeleteOrganizationByIds(c *gin.Context) {
var IDS request.IdsReq
_ = c.ShouldBindJSON(&IDS)
if err := orgService.DeleteOrganizationByIds(IDS); err != nil {
global.GVA_LOG.Error("批量删除失败!", zap.Error(err))
response.FailWithMessage("批量删除失败", c)
} else {
response.OkWithMessage("批量删除成功", c)
}
}
// UpdateOrganization 更新Organization
// @Tags Organization
// @Summary 更新Organization
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body organization.Organization true "更新Organization"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
// @Router /org/updateOrganization [put]
func (orgApi *OrganizationApi) UpdateOrganization(c *gin.Context) {
var org organization.Organization
_ = c.ShouldBindJSON(&org)
if err := orgService.UpdateOrganization(org); err != nil {
global.GVA_LOG.Error("更新失败!", zap.Error(err))
response.FailWithMessage("更新失败", c)
} else {
response.OkWithMessage("更新成功", c)
}
}
// FindOrganization 用id查询Organization
// @Tags Organization
// @Summary 用id查询Organization
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data query organization.Organization true "用id查询Organization"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
// @Router /org/findOrganization [get]
func (orgApi *OrganizationApi) FindOrganization(c *gin.Context) {
var org organization.Organization
_ = c.ShouldBindQuery(&org)
if reorg, err := orgService.GetOrganization(org.ID); err != nil {
global.GVA_LOG.Error("查询失败!", zap.Error(err))
response.FailWithMessage("查询失败", c)
} else {
response.OkWithData(gin.H{"reorg": reorg}, c)
}
}
// GetOrganizationList 分页获取Organization列表
// @Tags Organization
// @Summary 分页获取Organization列表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data query organizationReq.OrganizationSearch true "分页获取Organization列表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /org/getOrganizationList [get]
func (orgApi *OrganizationApi) GetOrganizationList(c *gin.Context) {
var pageInfo organizationReq.OrganizationSearch
_ = c.ShouldBindQuery(&pageInfo)
if list, total, err := orgService.GetOrganizationInfoList(pageInfo); err != nil {
global.GVA_LOG.Error("获取失败!", zap.Error(err))
response.FailWithMessage("获取失败", c)
} else {
response.OkWithDetailed(response.PageResult{
List: list,
Total: total,
Page: pageInfo.Page,
PageSize: pageInfo.PageSize,
}, "获取成功", c)
}
}
// GetOrganizationList 获取Organization树
// @Tags Organization
// @Summary 获取Organization树
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data query organizationReq.OrganizationSearch true "获取Organization树"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /org/getOrganizationTree [get]
func (orgApi *OrganizationApi) GetOrganizationTree(c *gin.Context) {
if tree, err := orgService.GetOrganizationTree(); err != nil {
global.GVA_LOG.Error("获取失败!", zap.Error(err))
response.FailWithMessage("获取失败", c)
} else {
response.OkWithDetailed(tree, "获取成功", c)
}
}
func (orgApi *OrganizationApi) CreateOrgUser(c *gin.Context) {
var orgUser organization.OrgUserReq
c.ShouldBindJSON(&orgUser)
if err := orgService.CreateOrgUser(orgUser); err != nil {
global.GVA_LOG.Error("变更失败!", zap.Error(err))
response.FailWithMessage("变更失败", c)
} else {
response.OkWithMessage("变更成功", c)
}
}
func (orgApi *OrganizationApi) FindOrgUserAll(c *gin.Context) {
org := c.Query("organizationID")
if UserIds, err := orgService.FindOrgUserAll(org); err != nil {
global.GVA_LOG.Error("查询失败!", zap.Error(err))
response.FailWithMessage("查询失败", c)
} else {
response.OkWithData(UserIds, c)
}
}
func (orgApi *OrganizationApi) FindOrgUserList(c *gin.Context) {
var pageInfo organizationReq.OrgUserSearch
c.ShouldBindQuery(&pageInfo)
if list, total, err := orgService.GetOrgUserList(pageInfo); err != nil {
global.GVA_LOG.Error("获取失败!", zap.Error(err))
response.FailWithMessage("获取失败", c)
} else {
response.OkWithDetailed(response.PageResult{
List: list,
Total: total,
Page: pageInfo.Page,
PageSize: pageInfo.PageSize,
}, "获取成功", c)
}
}
func (orgApi *OrganizationApi) SetOrgUserAdmin(c *gin.Context) {
var orgUser organization.OrgUser
c.ShouldBindJSON(&orgUser)
if err := orgService.SetOrgUserAdmin(orgUser.SysUserID, orgUser.IsAdmin); err != nil {
global.GVA_LOG.Error("设置失败!", zap.Error(err))
response.FailWithMessage("设置失败", c)
} else {
response.OkWithMessage("设置成功", c)
}
}
func (orgApi *OrganizationApi) SetOrgAuthority(c *gin.Context) {
var dataAuthority organization.DataAuthority
c.ShouldBindJSON(&dataAuthority)
if err := orgService.SetOrgAuthority(dataAuthority.AuthorityID, dataAuthority.AuthorityType); err != nil {
global.GVA_LOG.Error("设置失败!", zap.Error(err))
response.FailWithMessage("设置失败", c)
} else {
response.OkWithMessage("设置成功", c)
}
}
func (orgApi *OrganizationApi) SyncAuthority(c *gin.Context) {
if err := orgService.SyncAuthority(); err != nil {
global.GVA_LOG.Error("同步失败!", zap.Error(err))
response.FailWithMessage(err.Error(), c)
} else {
response.OkWithMessage("同步成功", c)
}
}
func (orgApi *OrganizationApi) GetAuthority(c *gin.Context) {
if authDataList, err := orgService.GetOrgAuthority(); err != nil {
global.GVA_LOG.Error("获取失败!", zap.Error(err))
response.FailWithMessage("获取失败", c)
} else {
response.OkWithData(authDataList, c)
}
}
func (orgApi *OrganizationApi) DeleteOrgUser(c *gin.Context) {
var orgUser organization.OrgUserReq
c.ShouldBindJSON(&orgUser)
if err := orgService.DeleteOrgUser(orgUser.SysUserIDS, orgUser.OrganizationID); err != nil {
global.GVA_LOG.Error("删除失败!", zap.Error(err))
response.FailWithMessage("删除失败", c)
} else {
response.OkWithMessage("删除成功", c)
}
}
func (orgApi *OrganizationApi) TransferOrgUser(c *gin.Context) {
var orgUser organization.OrgUserReq
c.ShouldBindJSON(&orgUser)
if err := orgService.TransferOrgUser(orgUser.SysUserIDS, orgUser.OrganizationID, orgUser.ToOrganizationID); err != nil {
global.GVA_LOG.Error("转移失败!", zap.Error(err))
response.FailWithMessage("转移失败", c)
} else {
response.OkWithMessage("转移成功", c)
}
}

View File

@ -0,0 +1,7 @@
package api
type ApiGroup struct {
OrganizationApi
}
var ApiGroupApp = new(ApiGroup)

View File

@ -0,0 +1 @@
package config

View File

@ -0,0 +1 @@
package global

View File

@ -0,0 +1,159 @@
package organization
import (
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/organization/model"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/organization/router"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/plugin-tool/utils"
"github.com/gin-gonic/gin"
)
type OrganizationPlugin struct {
}
func CreateOrganizationPlug() *OrganizationPlugin {
global.GVA_DB.AutoMigrate(model.Organization{}, model.OrgUser{}, model.DataAuthority{})
utils.RegisterMenus(
system.SysBaseMenu{
Path: "organizationGroup",
Name: "organizationGroup",
Hidden: false,
Component: "view/routerHolder.vue",
Sort: 1000,
Meta: system.Meta{
Title: "组织管理",
Icon: "school",
},
},
system.SysBaseMenu{
Path: "organization",
Name: "organization",
Hidden: false,
Component: "plugin/organization/view/index.vue",
Sort: 0,
Meta: system.Meta{
Title: "组织管理",
Icon: "school",
},
},
system.SysBaseMenu{
Path: "dataAuthority",
Name: "dataAuthority",
Hidden: false,
Component: "plugin/organization/view/dataAuthority.vue",
Sort: 1,
Meta: system.Meta{
Title: "资源管理",
Icon: "money",
},
},
)
utils.RegisterApis(
system.SysApi{
Path: "/org/createOrganization",
Description: "创建组织",
ApiGroup: "组织管理",
Method: "POST",
},
system.SysApi{
Path: "/org/deleteOrganization",
Description: "删除组织",
ApiGroup: "组织管理",
Method: "DELETE",
},
system.SysApi{
Path: "/org/deleteOrganizationByIds",
Description: "批量删除组织",
ApiGroup: "组织管理",
Method: "DELETE",
},
system.SysApi{
Path: "/org/updateOrganization",
Description: "更新组织",
ApiGroup: "组织管理",
Method: "PUT",
},
system.SysApi{
Path: "/org/createOrgUser",
Description: "添加组织成员",
ApiGroup: "组织管理",
Method: "POST",
},
system.SysApi{
Path: "/org/setOrgUserAdmin",
Description: "设置管理员",
ApiGroup: "组织管理",
Method: "PUT",
},
system.SysApi{
Path: "/org/findOrganization",
Description: "获取所选组织",
ApiGroup: "组织管理",
Method: "GET",
},
system.SysApi{
Path: "/org/getOrganizationList",
Description: "获取组织列表",
ApiGroup: "组织管理",
Method: "GET",
},
system.SysApi{
Path: "/org/getOrganizationTree",
Description: "获取所有组织树",
ApiGroup: "组织管理",
Method: "GET",
},
system.SysApi{
Path: "/org/findOrgUserAll",
Description: "获取组织下所有用户",
ApiGroup: "组织管理",
Method: "GET",
},
system.SysApi{
Path: "/org/findOrgUserList",
Description: "获取组织下所有用户(分页)",
ApiGroup: "组织管理",
Method: "GET",
},
system.SysApi{
Path: "/org/deleteOrgUser",
Description: "删除当前组织下选中用户",
ApiGroup: "组织管理",
Method: "DELETE",
},
system.SysApi{
Path: "/org/transferOrgUser",
Description: "用户转移组织",
ApiGroup: "组织管理",
Method: "PUT",
},
system.SysApi{
Path: "/org/setDataAuthority",
Description: "设置资源权限",
ApiGroup: "组织管理",
Method: "PUT",
},
system.SysApi{
Path: "/org/syncAuthority",
Description: "同步角色数据",
ApiGroup: "组织管理",
Method: "POST",
},
system.SysApi{
Path: "/org/getAuthority",
Description: "获取所有资源权限",
ApiGroup: "组织管理",
Method: "GET",
},
)
return &OrganizationPlugin{}
}
func (*OrganizationPlugin) Register(group *gin.RouterGroup) {
router.RouterGroupApp.InitOrganizationRouter(group)
}
func (*OrganizationPlugin) RouterPath() string {
return "org"
}

View File

@ -0,0 +1,45 @@
package model
import (
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
)
// Organization 结构体
// 如果含有time.Time 请自行import time包
type Organization struct {
global.GVA_MODEL
Name string `json:"name" form:"name" gorm:"column:name;comment:;"`
ParentID uint `json:"parentID" form:"parentID" gorm:"column:parent_id;comment:父节点ID;"`
Children []Organization `json:"children" gorm:"-"`
}
// TableName Organization 表名
func (Organization) TableName() string {
return "organization"
}
type OrgUser struct {
Organization Organization `json:"organization"`
OrganizationID uint `json:"organizationID,omitempty" form:"organizationID" `
SysUserID uint `json:"sysUserID,omitempty" form:"sysUserID"`
IsAdmin bool `json:"isAdmin" form:"isAdmin"`
SysUser system.SysUser `json:"sysUser"`
}
type DataAuthority struct {
AuthorityID uint `json:"authorityID" gorm:"column:authority_id;comment:角色ID;"`
Authority system.SysAuthority `json:"authority"`
AuthorityType int `json:"authorityType" gorm:"column:authority_type;comment:角色权限标记;"`
}
type OrgUserReq struct {
OrganizationID uint `json:"organizationID,omitempty"`
ToOrganizationID uint `json:"toOrganizationID,omitempty"`
SysUserIDS []uint `json:"sysUserIDS,omitempty"`
}
// TableName Organization 表名
func (OrgUser) TableName() string {
return "org_user"
}

View File

@ -0,0 +1,17 @@
package request
import (
"github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
organization "github.com/flipped-aurora/gin-vue-admin/server/plugin/organization/model"
)
type OrganizationSearch struct {
organization.Organization
request.PageInfo
}
type OrgUserSearch struct {
organization.OrgUser
UserName string `json:"userName" form:"userName"`
request.PageInfo
}

View File

@ -0,0 +1,7 @@
package router
type RouterGroup struct {
OrganizationRouter
}
var RouterGroupApp = new(RouterGroup)

View File

@ -0,0 +1,35 @@
package router
import (
"github.com/flipped-aurora/gin-vue-admin/server/middleware"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/organization/api"
"github.com/gin-gonic/gin"
)
type OrganizationRouter struct{}
func (s *OrganizationRouter) InitOrganizationRouter(Router *gin.RouterGroup) {
orgRouter := Router.Use(middleware.OperationRecord())
orgRouterWithoutRecord := Router
var orgApi = api.ApiGroupApp.OrganizationApi
{
orgRouter.POST("createOrganization", orgApi.CreateOrganization) // 新建Organization
orgRouter.DELETE("deleteOrganization", orgApi.DeleteOrganization) // 删除Organization
orgRouter.DELETE("deleteOrganizationByIds", orgApi.DeleteOrganizationByIds) // 批量删除Organization
orgRouter.PUT("updateOrganization", orgApi.UpdateOrganization) // 更新Organization
orgRouter.POST("createOrgUser", orgApi.CreateOrgUser) // 人员入职
orgRouter.PUT("setOrgUserAdmin", orgApi.SetOrgUserAdmin) // 管理员设置
orgRouter.PUT("setDataAuthority", orgApi.SetOrgAuthority) // 设置资源权限
orgRouter.POST("syncAuthority", orgApi.SyncAuthority) // 同步角色
orgRouter.GET("getAuthority", orgApi.GetAuthority) // 获取资源权限
}
{
orgRouterWithoutRecord.GET("findOrganization", orgApi.FindOrganization) // 根据ID获取Organization
orgRouterWithoutRecord.GET("getOrganizationList", orgApi.GetOrganizationList) // 获取Organization列表
orgRouterWithoutRecord.GET("getOrganizationTree", orgApi.GetOrganizationTree) // 获取Organization树
orgRouterWithoutRecord.GET("findOrgUserAll", orgApi.FindOrgUserAll) // 获取当前组织下所有用户ID
orgRouterWithoutRecord.GET("findOrgUserList", orgApi.FindOrgUserList) // 获取当前组织下所有用户(分页)
orgRouterWithoutRecord.DELETE("deleteOrgUser", orgApi.DeleteOrgUser) // 删除当前组织下选中用户
orgRouterWithoutRecord.PUT("transferOrgUser", orgApi.TransferOrgUser) // 用户转移组织
}
}

View File

@ -0,0 +1,7 @@
package service
type ServiceGroup struct {
OrganizationService
}
var ServiceGroupApp = new(ServiceGroup)

View File

@ -0,0 +1,255 @@
package service
import (
"errors"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
organization "github.com/flipped-aurora/gin-vue-admin/server/plugin/organization/model"
organizationReq "github.com/flipped-aurora/gin-vue-admin/server/plugin/organization/model/request"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/organization/utils"
"gorm.io/gorm"
)
type OrganizationService struct {
}
// CreateOrganization 创建Organization记录
// Author [piexlmax](https://github.com/piexlmax)
func (orgService *OrganizationService) CreateOrganization(org organization.Organization) (err error) {
err = global.GVA_DB.Create(&org).Error
return err
}
// DeleteOrganization 删除Organization记录
// Author [piexlmax](https://github.com/piexlmax)
func (orgService *OrganizationService) DeleteOrganization(org organization.Organization) (err error) {
err = global.GVA_DB.Where("parent_id = ?", org.ID).First(&organization.Organization{}).Error
if err == nil {
return errors.New("该组织有子组织,不能删除")
}
if errors.Is(err, gorm.ErrRecordNotFound) {
err = global.GVA_DB.Delete(&org, "id = ?", org.ID).Error
}
return err
}
// DeleteOrganizationByIds 批量删除Organization记录
// Author [piexlmax](https://github.com/piexlmax)
func (orgService *OrganizationService) DeleteOrganizationByIds(ids request.IdsReq) (err error) {
err = global.GVA_DB.Delete(&[]organization.Organization{}, "id in ?", ids.Ids).Error
return err
}
// UpdateOrganization 更新Organization记录
// Author [piexlmax](https://github.com/piexlmax)
func (orgService *OrganizationService) UpdateOrganization(org organization.Organization) (err error) {
var updatesmap = make(map[string]interface{})
updatesmap["Name"] = org.Name
updatesmap["ParentID"] = org.ParentID
err = global.GVA_DB.Model(&organization.Organization{}).Where("id = ?", org.ID).Updates(updatesmap).Error
return err
}
// GetOrganization 根据id获取Organization记录
// Author [piexlmax](https://github.com/piexlmax)
func (orgService *OrganizationService) GetOrganization(id uint) (org organization.Organization, err error) {
err = global.GVA_DB.Where("id = ?", id).First(&org).Error
return
}
// GetOrganizationInfoList 分页获取Organization记录
// Author [piexlmax](https://github.com/piexlmax)
func (orgService *OrganizationService) GetOrganizationInfoList(info organizationReq.OrganizationSearch) (list interface{}, total int64, err error) {
// 创建db
db := global.GVA_DB.Model(&organization.Organization{})
var orgs []organization.Organization
// 如果有条件搜索 下方会自动创建搜索语句
db = db.Where("parent_id = ?", info.ParentID)
if info.Name != "" {
db = db.Where("name LIKE ?", "%"+info.Name+"%")
}
err = db.Count(&total).Error
if err != nil {
return
}
err = db.Find(&orgs).Error
return orgs, total, err
}
func (orgService *OrganizationService) GetOrganizationTree() (OrgTree []organization.Organization, err error) {
var all []organization.Organization
err = global.GVA_DB.Find(&all).Error
if err != nil {
return
}
fmtOrgTree := orgService.fmtOrgTree(all, 0)
return fmtOrgTree, err
}
func (orgService *OrganizationService) fmtOrgTree(orgs []organization.Organization, pid uint) (tree []organization.Organization) {
for i := range orgs {
if orgs[i].ParentID == pid {
orgs[i].Children = orgService.fmtOrgTree(orgs, orgs[i].ID)
tree = append(tree, orgs[i])
}
}
return
}
func (orgService *OrganizationService) CreateOrgUser(orgUser organization.OrgUserReq) error {
var Users []organization.OrgUser
var CUsers []organization.OrgUser
err := global.GVA_DB.Find(&Users, "organization_id = ?", orgUser.OrganizationID).Error
if err != nil {
return err
}
var UserIdMap = make(map[uint]bool)
for i := range Users {
UserIdMap[Users[i].SysUserID] = true
}
for i := range orgUser.SysUserIDS {
if !UserIdMap[orgUser.SysUserIDS[i]] {
CUsers = append(CUsers, organization.OrgUser{SysUserID: orgUser.SysUserIDS[i], OrganizationID: orgUser.OrganizationID})
}
}
err = global.GVA_DB.Create(&CUsers).Error
return err
}
func (orgService *OrganizationService) FindOrgUserAll(orgID string) ([]uint, error) {
var Users []organization.OrgUser
var ids []uint
err := global.GVA_DB.Find(&Users, "organization_id = ?", orgID).Error
if err != nil {
return ids, err
}
for i := range Users {
ids = append(ids, Users[i].SysUserID)
}
return ids, err
}
// GetOrganizationInfoList 分页获取当前组织下用户记录
// Author [piexlmax](https://github.com/piexlmax)
func (orgService *OrganizationService) GetOrgUserList(info organizationReq.OrgUserSearch) (list interface{}, total int64, err error) {
limit := info.PageSize
offset := info.PageSize * (info.Page - 1)
// 创建db
db := global.GVA_DB.Model(&organization.OrgUser{}).Joins("SysUser").Preload("SysUser.Authority")
var orgs []organization.OrgUser
// 如果有条件搜索 下方会自动创建搜索语句
db = db.Where("organization_id = ?", info.OrganizationID)
if info.UserName != "" {
db = db.Where("SysUser.nick_name LIKE ?", "%"+info.UserName+"%")
}
err = db.Count(&total).Error
if err != nil {
return
}
err = db.Limit(limit).Offset(offset).Find(&orgs).Error
return orgs, total, err
}
func (orgService *OrganizationService) SetOrgUserAdmin(id uint, flag bool) (err error) {
return global.GVA_DB.Model(&organization.OrgUser{}).Where("sys_user_id = ?", id).Update("is_admin", flag).Error
}
func (orgService *OrganizationService) SetOrgAuthority(authID uint, authorityType int) (err error) {
return global.GVA_DB.Model(&organization.DataAuthority{}).Where("authority_id = ?", authID).Update("authority_type", authorityType).Error
}
func (orgService *OrganizationService) GetOrgAuthority() (authorityData []organization.DataAuthority, err error) {
err = global.GVA_DB.Preload("Authority").Find(&authorityData).Error
return authorityData, err
}
func (orgService *OrganizationService) SyncAuthority() (err error) {
var authData []system.SysAuthority
var auth []organization.DataAuthority
return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
var idMap = make(map[uint]*bool)
err := tx.Find(&authData).Error
if err != nil {
return err
}
for _, datum := range authData {
idMap[datum.AuthorityId] = utils.GetBoolPointer(true)
}
err = tx.Find(&auth).Error
if err != nil {
return err
}
for _, datum := range auth {
if idMap[datum.AuthorityID] != nil {
idMap[datum.AuthorityID] = utils.GetBoolPointer(false)
} else {
idMap[datum.AuthorityID] = nil
}
}
var ayncData []organization.DataAuthority
var deleteAuth []organization.DataAuthority
for k, _ := range idMap {
if idMap[k] != nil && *idMap[k] {
ayncData = append(ayncData, organization.DataAuthority{
AuthorityID: k,
AuthorityType: 0,
})
}
if idMap[k] == nil {
deleteAuth = append(deleteAuth, organization.DataAuthority{
AuthorityID: k,
AuthorityType: 0,
})
}
}
if len(ayncData) > 0 || len(deleteAuth) > 0 {
if len(ayncData) > 0 {
err := tx.Create(&ayncData).Error
if err != nil {
return err
}
}
if len(deleteAuth) > 0 {
var deleteAuthIds []uint
for i := range deleteAuth {
deleteAuthIds = append(deleteAuthIds, deleteAuth[i].AuthorityID)
}
err = tx.Delete(&deleteAuth, "authority_id in (?)", deleteAuthIds).Error
if err != nil {
return err
}
}
return nil
} else {
return errors.New("当前无需同步")
}
})
}
func (orgService *OrganizationService) DeleteOrgUser(ids []uint, orgID uint) (err error) {
return global.GVA_DB.Where("sys_user_id in (?) and organization_id = ?", ids, orgID).Delete(&[]organization.OrgUser{}).Error
}
func (orgService *OrganizationService) TransferOrgUser(ids []uint, orgID, toOrgID uint) (err error) {
return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
var CUsers []organization.OrgUser
err := global.GVA_DB.Where("sys_user_id in (?) and organization_id in (?)", ids, []uint{orgID, toOrgID}).Delete(&[]organization.OrgUser{}).Error
if err != nil {
return err
}
for i := range ids {
CUsers = append(CUsers, organization.OrgUser{SysUserID: ids[i], OrganizationID: toOrgID})
}
err = global.GVA_DB.Create(&CUsers).Error
if err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,195 @@
package utils
import (
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/organization/model"
"github.com/flipped-aurora/gin-vue-admin/server/utils"
"github.com/gin-gonic/gin"
)
// uint 去重方法
func Uniq(array []uint) []uint {
var uintMap = make(map[uint]bool)
var res []uint
for _, u := range array {
if !uintMap[u] {
uintMap[u] = true
res = append(res, u)
}
}
return res
}
const (
Node = 0 // 无资源权限
Self = 1 // 仅自己
Current = 2 // 当前部门
Deep = 3 // 当前部门及以下
All = 4 // 所有
)
// 获取当前部门ID
func GetSelfOrg(id uint) []uint {
var orgUser []model.OrgUser
err := global.GVA_DB.Find(&orgUser, "sys_user_id = ?", id).Error
if err != nil {
return []uint{}
}
var orgId []uint
for _, m := range orgUser {
orgId = append(orgId, m.OrganizationID)
}
return Uniq(orgId)
}
// 获取所有部门
func GetAllOrg() []model.Organization {
var orgUser []model.Organization
err := global.GVA_DB.Find(&orgUser).Error
if err != nil {
return []model.Organization{}
}
return orgUser
}
// 获取所有部门ID
func GetAllOrgID() []uint {
orgUser := GetAllOrg()
if len(orgUser) == 0 {
return []uint{}
}
var orgids []uint
for _, organization := range orgUser {
orgids = append(orgids, organization.ID)
}
return Uniq(orgids)
}
// 获取当前部门及以下部门id
func GetDeepOrg(id uint) []uint {
orgId := GetSelfOrg(id)
if len(orgId) == 0 {
return []uint{}
}
orgs := GetAllOrg()
if len(orgs) == 0 {
return []uint{}
}
orgids := findChildren(orgId, orgs)
return Uniq(append(orgids, orgId...))
}
// 获取当前部门及以下部门的递归方法
func findChildren(ids []uint, orgs []model.Organization) []uint {
var idsMap = make(map[uint]bool)
var resIDs []uint
for _, id := range ids {
idsMap[id] = true
}
for _, org := range orgs {
if idsMap[org.ParentID] {
resIDs = append(resIDs, org.ID)
}
}
if len(resIDs) == 0 {
resIDs = append(resIDs, ids...)
return resIDs
}
dids := findChildren(resIDs, orgs)
resIDs = append(resIDs, ids...)
resIDs = append(resIDs, dids...)
return resIDs
}
// 获取当前部门的用户id
func GetCurrentUserIDs(id uint) []uint {
orgId := GetSelfOrg(id)
if len(orgId) == 0 {
return []uint{}
}
return GetUsersByOrgIds(orgId)
}
// 获取当前部门及以下的用户id
func GetDeepUserIDs(id uint) []uint {
orgids := GetDeepOrg(id)
if len(orgids) == 0 {
return []uint{}
}
return GetUsersByOrgIds(orgids)
}
// 根据部门获取部门下用户ID
func GetUsersByOrgIds(orgIds []uint) []uint {
var orgUser []model.OrgUser
err := global.GVA_DB.Find(&orgUser, "organization_id in (?)", orgIds).Error
if err != nil {
return []uint{}
}
var userIDS []uint
for _, m := range orgUser {
userIDS = append(userIDS, m.SysUserID)
}
return Uniq(userIDS)
}
// 获取所有用户ID
func GetAllUserIDs() []uint {
var users []system.SysUser
err := global.GVA_DB.Find(&users).Error
if err != nil {
return []uint{}
}
var usersID []uint
for _, sysUser := range users {
usersID = append(usersID, sysUser.ID)
}
return Uniq(usersID)
}
// 自动获取当前用户拥有的权限的用户ID
func GetUserIDS(c *gin.Context) []uint {
user := utils.GetUserInfo(c)
var data model.DataAuthority
err := global.GVA_DB.First(&data, "authority_id = ?", user.AuthorityId).Error
if err != nil {
return []uint{}
}
switch data.AuthorityType {
case Node:
return []uint{}
case Self:
return []uint{user.BaseClaims.ID}
case Current:
return GetCurrentUserIDs(user.BaseClaims.ID)
case Deep:
return GetDeepUserIDs(user.BaseClaims.ID)
case All:
return GetAllUserIDs()
}
return []uint{}
}
// 自动获取当前用户拥有的权限的部门ID
func GetOrgIDS(c *gin.Context) []uint {
user := utils.GetUserInfo(c)
var data model.DataAuthority
err := global.GVA_DB.First(&data, "authority_id = ?", user.AuthorityId).Error
if err != nil {
return []uint{}
}
switch data.AuthorityType {
case Node:
return []uint{}
case Self:
return GetSelfOrg(user.BaseClaims.ID)
case Current:
return GetSelfOrg(user.BaseClaims.ID)
case Deep:
return GetDeepOrg(user.BaseClaims.ID)
case All:
return GetAllOrgID()
}
return []uint{}
}

View File

@ -0,0 +1,14 @@
package utils
import (
"github.com/flipped-aurora/gin-vue-admin/server/core"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/initialize"
"testing"
)
func TestGetAllUserIDs(t *testing.T) {
global.GVA_VP = core.Viper() // 初始化Viper
global.GVA_LOG = core.Zap() // 初始化zap日志库
global.GVA_DB = initialize.Gorm() // gorm连接数据库
}

View File

@ -0,0 +1,160 @@
aliyun-oss:
endpoint: yourEndpoint
access-key-id: yourAccessKeyId
access-key-secret: yourAccessKeySecret
bucket-name: yourBucketName
bucket-url: yourBucketUrl
base-path: yourBasePath
autocode:
transfer-restart: true
root: E:\gin-vue-admin
server: /server
server-api: /api/v1/%s
server-plug: /plugin/%s
server-initialize: /initialize
server-model: /model/%s
server-request: /model/%s/request/
server-router: /router/%s
server-service: /service/%s
web: /web/src
web-api: /api
web-form: /view
web-table: /view
aws-s3:
bucket: xxxxx-10005608
region: ap-shanghai
endpoint: ""
s3-force-path-style: false
disable-ssl: false
secret-id: xxxxxxxx
secret-key: xxxxxxxx
base-url: https://gin.vue.admin
path-prefix: github.com/flipped-aurora/gin-vue-admin/server
captcha:
key-long: 6
img-width: 240
img-height: 80
cors:
mode: whitelist
whitelist:
- allow-origin: example1.com
allow-methods: GET, POST
allow-headers: content-type
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,
Content-Type
allow-credentials: true
- allow-origin: example2.com
allow-methods: GET, POST
allow-headers: content-type
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,
Content-Type
allow-credentials: true
db-list:
- disable: false
type: ""
alias-name: ""
path: ""
port: ""
config: ""
db-name: ""
username: ""
password: ""
max-idle-conns: 10
max-open-conns: 100
log-mode: ""
log-zap: false
email:
to: xxx@qq.com
port: 465
from: xxx@163.com
host: smtp.163.com
is-ssl: true
secret: xxx
nickname: test
excel:
dir: ./resource/excel/
hua-wei-obs:
path: you-path
bucket: you-bucket
endpoint: you-endpoint
access-key: you-access-key
secret-key: you-secret-key
jwt:
signing-key: 3a300b4a-3352-406d-ade3-0dac0b39cf60
expires-time: 604800
buffer-time: 86400
issuer: qmPlus
local:
path: uploads/file
store-path: uploads/file
mysql:
path: 127.0.0.1
port: "3306"
config: charset=utf8mb4&parseTime=True&loc=Local
db-name: gva
username: root
password: Aa@6447985
max-idle-conns: 10
max-open-conns: 100
log-mode: error
log-zap: false
pgsql:
path: ""
port: ""
config: ""
db-name: ""
username: ""
password: ""
max-idle-conns: 10
max-open-conns: 100
log-mode: ""
log-zap: false
qiniu:
zone: ZoneHuaDong
bucket: ""
img-path: ""
use-https: falsee
access-key: ""
secret-key: ""
use-cdn-domains: false
redis:
db: 0
addr: 127.0.0.1:6379
password: ""
system:
env: public
addr: 8888
db-type: mysql
oss-type: local
use-multipoint: false
use-redis: false
iplimit-count: 15000
iplimit-time: 3600
tencent-cos:
bucket: xxxxx-10005608
region: ap-shanghai
secret-id: xxxxxxxx
secret-key: xxxxxxxx
base-url: https://gin.vue.admin
path-prefix: github.com/flipped-aurora/gin-vue-admin/server
timer:
start: true
spec: '@daily'
with_seconds: false
detail:
- tableName: sys_operation_records
compareField: created_at
interval: 2160h
- tableName: jwt_blacklists
compareField: created_at
interval: 168h
zap:
level: info
prefix: '[github.com/flipped-aurora/gin-vue-admin/server]'
format: console
director: log
encode-level: LowercaseColorLevelEncoder
stacktrace-key: stacktrace
max-age: 30
show-line: true
log-in-console: true

View File

@ -0,0 +1,5 @@
package utils
func GetBoolPointer(t bool) *bool {
return &t
}

View File

@ -1,10 +1,10 @@
{"weakness":false, {"weakness":false,
"grey":false, "grey":false,
"primaryColor":"#3b82f6", "primaryColor":"#3b82f6",
"showTabs":true, "showTabs":true,
"darkMode":"auto", "darkMode":"auto",
"layout_side_width":200, "layout_side_width":150,
"layout_side_collapsed_width":60, "layout_side_collapsed_width":60,
"layout_side_item_height":44, "layout_side_item_height":44,
"show_watermark":true, "show_watermark":true,
"side_mode":"normal"} "side_mode":"combination"}

View File

@ -0,0 +1,127 @@
import service from '@/utils/request'
export const createOrganization = (data) => {
return service({
url: '/org/createOrganization',
method: 'post',
data
})
}
export const findOrganization = (params) => {
return service({
url: '/org/findOrganization',
method: 'get',
params
})
}
export const updateOrganization = (data) => {
return service({
url: '/org/updateOrganization',
method: 'put',
data
})
}
export const deleteOrganizationByIds = (data) => {
return service({
url: '/org/deleteOrganizationByIds',
method: 'delete',
data
})
}
export const deleteOrganization = (data) => {
return service({
url: '/org/deleteOrganization',
method: 'delete',
data
})
}
export const getOrganizationList = (params) => {
return service({
url: '/org/getOrganizationList',
method: 'get',
params
})
}
export const getOrganizationTree = () => {
return service({
url: '/org/getOrganizationTree',
method: 'get',
})
}
export const findOrgUserAll = (params) => {
return service({
url: '/org/findOrgUserAll',
method: 'get',
params
})
}
export const createOrgUser = (data) => {
return service({
url: '/org/createOrgUser',
method: 'post',
data
})
}
export const findOrgUserList = (params) => {
return service({
url: '/org/findOrgUserList',
method: 'get',
params
})
}
export const setOrgUserAdmin = (data) => {
return service({
url: '/org/setOrgUserAdmin',
method: 'put',
data
})
}
export const deleteOrgUserApi = (data) => {
return service({
url: '/org/deleteOrgUser',
method: 'delete',
data
})
}
export const transferOrgUserApi = (data) => {
return service({
url: '/org/transferOrgUser',
method: 'put',
data
})
}
export const setDataAuthority = (data) => {
return service({
url: '/org/setDataAuthority',
method: 'put',
data
})
}
export const syncAuthority = () => {
return service({
url: '/org/syncAuthority',
method: 'post'
})
}
export const getAuthority = () => {
return service({
url: '/org/getAuthority',
method: 'get'
})
}

View File

@ -0,0 +1,71 @@
<template>
<div class="organization">
<div class="gva-search-box org-top">
资源权限管理
</div>
<div class="gva-table-box">
<div class="gva-btn-list">
<el-button size="small" type="primary" icon="plus" @click="syncAuthorityFun()">同步角色数据</el-button>
</div>
<el-table
:data="tableData"
row-key="authorityId"
style="width: 100%"
>
<el-table-column label="角色ID" min-width="180" prop="authorityID" />
<el-table-column align="left" label="角色名称" min-width="180" prop="authority.authorityName" />
<el-table-column label="资源权限" min-width="180" prop="authorityType">
<template #default="{row}">
<el-select v-model="row.authorityType" @change="(val)=>{setDataAuthorityFun(row,val)}">
<el-option label="无资源权限" :value="0" />
<el-option label="仅本人" :value="1" />
<el-option label="本部门" :value="2" />
<el-option label="部门及以下" :value="3" />
<el-option label="全部" :value="4" />
</el-select>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { setDataAuthority,
syncAuthority,
getAuthority,
} from '@/plugin/organization/api/organization'
import { ElMessage } from 'element-plus'
const tableData = ref([])
const getTableData = async() => {
const res = await getAuthority()
tableData.value = res.data
}
getTableData()
const syncAuthorityFun = async() => {
const res = await syncAuthority()
if (res.code === 0) {
ElMessage.success('同步完成')
getTableData()
}
}
const setDataAuthorityFun = async(row, val) => {
const res = await setDataAuthority({ authorityID: row.authorityID, authorityType: val })
if (res.code === 0) {
ElMessage.success('设置成功')
}
getTableData()
}
</script>
<style scoped lang="scss">
.org-top{
padding-bottom: 20px;
}
</style>

View File

@ -0,0 +1,662 @@
<template>
<div class="p-4">
<div class="gva-organization-box">
<div class="gva-organization-box-left">
<div class="toolbar">
<el-button
type="primary"
@click="addOrg(0)"
>新增组织</el-button>
</div>
<div class="tree-body">
<el-tree
ref="treeRef"
:data="treeData"
default-expand-all
node-key="ID"
:props="defaultProps"
:expand-on-click-node="false"
highlight-current
@current-change="getNowOrg"
>
<template #default="{ node ,data }">
<span class="tree-body-tree-node">
<el-tooltip
class="box-item"
effect="dark"
:show-after="600"
:content="node.label"
placement="top-start"
>
<span class="tree-body-tree-node-label">{{ node.label }}</span>
</el-tooltip>
<span>
<el-dropdown>
<span class="el-more-filled">
<el-icon><more-filled /></el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="addOrg(data.ID)">
<el-icon><Plus /></el-icon>
新增子组织</el-dropdown-item>
<el-dropdown-item @click="editOrg(data)">
<el-icon><CirclePlus /></el-icon>
编辑组织</el-dropdown-item>
<el-dropdown-item @click="deleteOrg(data)">
<el-icon><Delete /></el-icon>
删除组织</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</span>
</span>
</template>
</el-tree>
</div>
</div>
<div class="gva-organization-box-right">
<div class="toolbar">
<div class="toolbar-search">
<el-input
v-model="userSearch.userName"
placeholder="请输入要搜索的用户名"
/>
<el-button
type="primary"
@click="getUserTable"
>搜索</el-button>
</div>
<div>
<el-button
type="primary"
@click="openTransferOrgUser()"
>更换组织</el-button>
<el-button
type="primary"
@click="deleteUser(selectData.map(item=>item.sysUser.ID))"
>踢出组织</el-button>
<el-button
type="primary"
@click="addUser"
>人员入职</el-button>
</div>
</div>
<div class="table-body">
<el-table
:data="userTable"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55"
/>
<el-table-column
prop="sysUser.nickName"
label="姓名"
width="120"
/>
<el-table-column
prop="sysUser.authority.authorityName"
label="用户角色"
width="120"
/>
<el-table-column
prop="isAdmin"
label="是否管理员"
width="120"
>
<template #default="{row}">
{{ row.isAdmin?"是":"否" }}
</template>
</el-table-column>
<el-table-column
label="操作列"
min-width="220"
>
<template #default="{row}">
<el-button
link
type="primary"
@click="openTransferOrgUser(row.sysUser.ID)"
> 更换组织</el-button>
<el-button
link
type="primary"
@click="deleteUser([row.sysUser.ID])"
> 踢出组织</el-button>
<el-button
v-if="!row.isAdmin"
link
type="primary"
@click="setAdmin(row.sysUser.ID,true)"
> 设置管理员</el-button>
<el-button
v-else
link
type="primary"
@click="setAdmin(row.sysUser.ID,false)"
> 取消管理员</el-button>
</template>
</el-table-column>
</el-table>
<div class="gva-pagination">
<el-pagination
:current-page="page"
:page-size="pageSize"
:page-sizes="[10, 30, 50, 100]"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
/>
</div>
</div>
</div>
</div>
<el-dialog
v-model="orgDialog"
:before-close="orgClear"
title="组织管理"
>
<el-form
:model="orgForm"
label-width="120px"
>
<el-form-item label="父组织">
<el-tree-select
v-model="orgForm.parentID"
:data="[{ID:0,name:'根组织'},...treeData]"
check-strictly
:props="defaultProps"
:render-after-expand="false"
/>
</el-form-item>
<el-form-item label="组织名称">
<el-input v-model="orgForm.name" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="orgClear">取消</el-button>
<el-button
type="primary"
@click="orgEnter"
>确认</el-button>
</template>
</el-dialog>
<el-dialog
v-model="orgUserDialog"
title="组织人员"
>
<el-form
v-model="orgUserForm"
label-width="120px"
>
<el-form-item label="组织">
<el-tree-select
v-model="orgUserForm.organizationID"
:data="[{ID:0,name:'根组织'},...treeData]"
check-strictly
:props="defaultProps"
:render-after-expand="false"
disabled
/>
</el-form-item>
<el-form-item label="成员">
<el-select
v-model="orgUserForm.sysUserIDS"
placeholder="请选择需要加入组织的成员"
multiple
filterable
>
<el-option
v-for="item in userList"
:key="item.ID"
:disabled="disabledUserMap[item.ID]"
:label="item.nickName"
:value="item.ID"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="orgUserClear">取消</el-button>
<el-button
type="primary"
@click="orgUserEnter"
>确定</el-button>
</template>
</el-dialog>
<el-dialog
v-model="transferOrgUserFlag"
title="更换组织"
>
<el-form
v-model="targetOrg"
label-width="120px"
>
<el-form-item label="父组织">
<el-tree-select
v-model="targetOrg.toOrganizationID"
:data="[{ID:0,name:'根组织'},...treeData]"
check-strictly
:props="defaultProps"
:render-after-expand="false"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="cloesTransferOrgUser">取消</el-button>
<el-button
type="primary"
@click="transferOrgUser"
>确定</el-button>
</template>
</el-dialog>
</div>
</template>
<script>
import { ref } from 'vue'
import { createOrganization,
deleteOrganization,
getOrganizationTree,
updateOrganization,
findOrganization,
findOrgUserAll,
createOrgUser,
findOrgUserList,
setOrgUserAdmin,
deleteOrgUserApi,
transferOrgUserApi
} from '@/plugin/organization/api/organization'
import { getUserList } from '@/api/user.js'
import { ElMessageBox, ElMessage } from 'element-plus'
export default {
name: 'Organization',
}
</script>
<script setup>
const defaultProps = {
value: 'ID',
children: 'children',
label: 'name',
}
const currentOrg = ref(0)
const data = ref([])
const orgDialog = ref(false)
const selectData = ref([])
//
const treeData = ref([])
const getOrganizationTreeFunc = async() => {
const res = await getOrganizationTree()
if (res.code === 0 && res.data !== null) {
treeData.value = res.data
}
}
const orgForm = ref({
ID: 0,
parentID: 0,
name: '',
})
//
const orgType = ref('add')
//
const addOrg = (ID) => {
orgForm.value = {
ID: 0,
parentID: ID,
name: '',
}
orgType.value = 'add'
orgDialog.value = true
}
//
const orgClear = () => {
orgForm.value = {
ID: 0,
parentID: 0,
name: '',
}
setDisabled(treeData.value, false)
orgDialog.value = false
}
const setDisabled = (treeNodes, disabled) => {
treeNodes.forEach((node) => {
node.disabled = disabled
if (node.children) {
setDisabled(node.children, disabled)
}
})
}
// IDdisabled
const findNode = (nodes, ID) => {
console.log(1)
nodes.forEach((node) => {
if (node.ID === ID) {
setDisabled([node], true)
}
if (node.children) {
findNode(node.children, ID)
}
})
}
//
const editOrg = async(row) => {
const res = await findOrganization({ ID: row.ID })
if (res.code === 0) {
findNode(treeData.value, row.ID)
orgForm.value = {
ID: res.data.reorg.ID,
parentID: res.data.reorg.parentID,
name: res.data.reorg.name,
}
orgType.value = 'edit'
orgDialog.value = true
}
}
//
const deleteOrg = async(row) => {
ElMessageBox.confirm('确定删除该组织吗?', '提示', {
type: 'warning',
confirmButtonText: '确定',
cancelButtonText: '取消',
showClose: false,
}).then(async() => {
const res = await deleteOrganization({
ID: row.ID,
})
if (res.code === 0) {
ElMessage.success('删除成功')
getOrganizationTreeFunc()
}
}).catch(() => {
ElMessage.info('取消删除')
})
}
//
const orgEnter = async() => {
switch (orgType.value) {
case 'add':
{
const res = await createOrganization(orgForm.value)
if (res.code === 0) {
orgClear()
getOrganizationTreeFunc()
}
break
}
case 'edit':
{
const res = await updateOrganization(orgForm.value)
if (res.code === 0) {
orgClear()
getOrganizationTreeFunc()
}
break
}
default:
break
}
}
// end
//
//
const handleSelectionChange = (val) => {
selectData.value = val
}
const disabledUserMap = ref({})
//
const orgUserDialog = ref(false)
//
const orgUserForm = ref({
sysUserIDS: [],
organizationID: '',
})
//
const addUser = async() => {
disabledUserMap.value = {}
const res = await findOrgUserAll({ organizationID: currentOrg.value })
if (res.code === 0) {
res.data && res.data.forEach(item => {
disabledUserMap.value[item] = true
})
}
orgUserForm.value.organizationID = currentOrg.value
orgUserDialog.value = true
}
//
const getNowOrg = (e) => {
currentOrg.value = e.ID
getUserTable()
}
//
const treeRef = ref(null)
//
const setAdmin = async(id, flag) => {
const res = await setOrgUserAdmin({
sysUserID: id,
isAdmin: flag
})
if (res.code === 0) {
ElMessage.success('设置成功')
getUserTable()
}
}
//
const userTable = ref([])
const page = ref(1)
const pageSize = ref(10)
const total = ref(0)
const handleCurrentChange = (e) => {
page.value = e
getUserTable()
}
const handleSizeChange = (e) => {
pageSize.value = e
getUserTable()
}
//
const getUserTable = async() => {
const res = await findOrgUserList({ organizationID: currentOrg.value, page: page.value, pageSize: pageSize.value, ...userSearch.value })
if (res.code === 0) {
page.value = res.data.page
pageSize.value = res.data.pageSize
total.value = res.data.total
userTable.value = res.data.list
}
}
//
const userList = ref([])
//
const userSearch = ref({
userName: '',
})
//
const deleteUser = async(sysUserIDS) => {
ElMessageBox.confirm('确定删除选中用户吗?', '提示', {
type: 'warning',
confirmButtonText: '确定',
cancelButtonText: '取消',
showClose: false,
}).then(async() => {
const res = await deleteOrgUserApi({ sysUserIDS, organizationID: currentOrg.value })
if (res.code === 0) {
ElMessage.success('删除成功')
getUserTable()
selectData.value = []
}
}).catch(() => {
ElMessage.info('取消删除')
})
}
//
const getAllUser = async(e) => {
const res = await getUserList({ page: 1, pageSize: 9999 })
userList.value = res.data.list
total.value = res.data.total
}
//
const orgUserClear = () => {
orgUserForm.value.sysUserIDS = []
orgUserDialog.value = false
}
//
const targetOrg = ref({
sysUserIDS: [],
organizationID: 0,
toOrganizationID: undefined,
})
//
const transferOrgUserFlag = ref(false)
//
const openTransferOrgUser = (sysUserID) => {
targetOrg.value.organizationID = currentOrg.value
if (sysUserID) {
targetOrg.value.sysUserIDS = [sysUserID]
} else {
targetOrg.value.sysUserIDS = selectData.value.map(item => item.sysUser.ID)
}
transferOrgUserFlag.value = true
}
//
const cloesTransferOrgUser = () => {
transferOrgUserFlag.value = false
targetOrg.value.sysUserIDS = []
targetOrg.value.toOrganizationID = undefined
}
//
const transferOrgUser = async() => {
const res = await transferOrgUserApi(targetOrg.value)
if (res.code === 0) {
ElMessage.success('转移成功')
getUserTable()
selectData.value = []
cloesTransferOrgUser()
}
}
//
const orgUserEnter = async() => {
orgUserDialog.value = false
const res = await createOrgUser(orgUserForm.value)
if (res.code === 0) {
ElMessage.success('添加成功')
orgUserClear()
getUserTable()
}
}
//
const init = async() => {
await getOrganizationTreeFunc()
treeRef.value.setCurrentKey(treeData.value[0].ID)
getAllUser()
currentOrg.value = treeData.value[0].ID
getUserTable()
}
init()
</script>
<style scope lang="scss">
.org-top{
padding-bottom: 20px;
}
.gva-organization-box{
@apply flex flex-row justify-between h-[calc(100vh-170px)] gap-2;
&-left{
@apply w-80 box-border p-4 dark:bg-slate-900 bg-white;
&>.toolbar{
@apply mb-4;
}
.tree-body-tree-node{
@apply flex justify-between pr-4 flex-1;
&-label{
@apply flex-1;
max-width: 100px;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
}
}
&>.tree-body{
height: calc(100% - 52px);
overflow: auto;
&::-webkit-scrollbar{
width: 2px;
height: 2px;
}
}
}
&-right{
@apply w-[calc(100%-90px)] box-border p-4 dark:bg-slate-900 bg-white;
&>.toolbar{
padding-bottom: 20px;
display: flex;
justify-content: space-between;
.toolbar-search{
display: flex;
align-items: center;
margin-bottom: 20px;
.el-input{
flex: 1;
}
.el-button{
margin-left: 10px;
}
}
}
width: calc(100% - 270px);
}
}
</style>