diff --git a/backend/model/menu_entity.go b/backend/model/menu_entity.go new file mode 100644 index 0000000..37e2504 --- /dev/null +++ b/backend/model/menu_entity.go @@ -0,0 +1,23 @@ +package model + +import "time" + +// Menu 菜单模型 +type Menu struct { + Id int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` + ParentId int64 `gorm:"column:parent_id;default:0;index" json:"parentId"` + Name string `gorm:"column:name;type:varchar(50);not null" json:"name"` + Path string `gorm:"column:path;type:varchar(200);default:''" json:"path"` + Icon string `gorm:"column:icon;type:varchar(50);default:''" json:"icon"` + Component string `gorm:"column:component;type:varchar(200);default:''" json:"component"` + Type string `gorm:"column:type;type:varchar(20);default:'config'" json:"type"` // default or config + SortOrder int `gorm:"column:sort_order;default:0" json:"sortOrder"` + Visible bool `gorm:"column:visible;default:true" json:"visible"` + Status int `gorm:"column:status;default:1" json:"status"` + CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"createdAt"` + UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updatedAt"` +} + +func (Menu) TableName() string { + return "menu" +} diff --git a/backend/model/menu_model.go b/backend/model/menu_model.go new file mode 100644 index 0000000..4a79024 --- /dev/null +++ b/backend/model/menu_model.go @@ -0,0 +1,64 @@ +package model + +import ( + "context" + "errors" + + "gorm.io/gorm" +) + +// MenuInsert 插入菜单 +func MenuInsert(ctx context.Context, db *gorm.DB, menu *Menu) (int64, error) { + result := db.WithContext(ctx).Create(menu) + if result.Error != nil { + return 0, result.Error + } + return menu.Id, nil +} + +// MenuFindOne 根据ID查询菜单 +func MenuFindOne(ctx context.Context, db *gorm.DB, id int64) (*Menu, error) { + var menu Menu + result := db.WithContext(ctx).First(&menu, id) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, ErrNotFound + } + return nil, result.Error + } + return &menu, nil +} + +// MenuFindAll 查询所有启用的菜单(排序) +func MenuFindAll(ctx context.Context, db *gorm.DB) ([]Menu, error) { + var menus []Menu + err := db.WithContext(ctx).Where("status = 1").Order("sort_order ASC, id ASC").Find(&menus).Error + return menus, err +} + +// MenuFindByIds 根据ID列表查询菜单 +func MenuFindByIds(ctx context.Context, db *gorm.DB, ids []int64) ([]Menu, error) { + var menus []Menu + if len(ids) == 0 { + return menus, nil + } + err := db.WithContext(ctx).Where("id IN ? AND status = 1", ids).Order("sort_order ASC, id ASC").Find(&menus).Error + return menus, err +} + +// MenuUpdate 更新菜单 +func MenuUpdate(ctx context.Context, db *gorm.DB, menu *Menu) error { + return db.WithContext(ctx).Save(menu).Error +} + +// MenuDelete 删除菜单 +func MenuDelete(ctx context.Context, db *gorm.DB, id int64) error { + return db.WithContext(ctx).Delete(&Menu{}, id).Error +} + +// MenuHasChildren 检查菜单是否有子菜单 +func MenuHasChildren(ctx context.Context, db *gorm.DB, parentId int64) (bool, error) { + var count int64 + err := db.WithContext(ctx).Model(&Menu{}).Where("parent_id = ?", parentId).Count(&count).Error + return count > 0, err +} diff --git a/backend/model/organization_entity.go b/backend/model/organization_entity.go new file mode 100644 index 0000000..cca03bb --- /dev/null +++ b/backend/model/organization_entity.go @@ -0,0 +1,22 @@ +package model + +import "time" + +// Organization 机构模型(树形) +type Organization struct { + Id int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` + ParentId int64 `gorm:"column:parent_id;default:0;index" json:"parentId"` + Name string `gorm:"column:name;type:varchar(100);not null" json:"name"` + Code string `gorm:"column:code;type:varchar(50);uniqueIndex" json:"code"` + Leader string `gorm:"column:leader;type:varchar(50);default:''" json:"leader"` + Phone string `gorm:"column:phone;type:varchar(20);default:''" json:"phone"` + Email string `gorm:"column:email;type:varchar(100);default:''" json:"email"` + SortOrder int `gorm:"column:sort_order;default:0" json:"sortOrder"` + Status int `gorm:"column:status;default:1" json:"status"` + CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"createdAt"` + UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updatedAt"` +} + +func (Organization) TableName() string { + return "organization" +} diff --git a/backend/model/organization_model.go b/backend/model/organization_model.go new file mode 100644 index 0000000..3af2cbd --- /dev/null +++ b/backend/model/organization_model.go @@ -0,0 +1,67 @@ +package model + +import ( + "context" + "errors" + + "gorm.io/gorm" +) + +// OrgInsert 插入机构 +func OrgInsert(ctx context.Context, db *gorm.DB, org *Organization) (int64, error) { + result := db.WithContext(ctx).Create(org) + if result.Error != nil { + return 0, result.Error + } + return org.Id, nil +} + +// OrgFindOne 根据ID查询机构 +func OrgFindOne(ctx context.Context, db *gorm.DB, id int64) (*Organization, error) { + var org Organization + result := db.WithContext(ctx).First(&org, id) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, ErrNotFound + } + return nil, result.Error + } + return &org, nil +} + +// OrgFindAll 查询所有启用的机构 +func OrgFindAll(ctx context.Context, db *gorm.DB) ([]Organization, error) { + var orgs []Organization + err := db.WithContext(ctx).Where("status = 1").Order("sort_order ASC, id ASC").Find(&orgs).Error + return orgs, err +} + +// OrgUpdate 更新机构 +func OrgUpdate(ctx context.Context, db *gorm.DB, org *Organization) error { + return db.WithContext(ctx).Save(org).Error +} + +// OrgDelete 删除机构 +func OrgDelete(ctx context.Context, db *gorm.DB, id int64) error { + return db.WithContext(ctx).Delete(&Organization{}, id).Error +} + +// OrgHasChildren 检查是否有子机构 +func OrgHasChildren(ctx context.Context, db *gorm.DB, parentId int64) (bool, error) { + var count int64 + err := db.WithContext(ctx).Model(&Organization{}).Where("parent_id = ? AND status = 1", parentId).Count(&count).Error + return count > 0, err +} + +// OrgFindOneByCode 根据编码查询机构 +func OrgFindOneByCode(ctx context.Context, db *gorm.DB, code string) (*Organization, error) { + var org Organization + result := db.WithContext(ctx).Where("code = ?", code).First(&org) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, ErrNotFound + } + return nil, result.Error + } + return &org, nil +} diff --git a/backend/model/role_entity.go b/backend/model/role_entity.go new file mode 100644 index 0000000..e0a360c --- /dev/null +++ b/backend/model/role_entity.go @@ -0,0 +1,20 @@ +package model + +import "time" + +// Role 角色模型 +type Role struct { + Id int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` + Name string `gorm:"column:name;type:varchar(50);not null" json:"name"` + Code string `gorm:"column:code;type:varchar(50);uniqueIndex;not null" json:"code"` + Description string `gorm:"column:description;type:varchar(255);default:''" json:"description"` + IsSystem bool `gorm:"column:is_system;default:false" json:"isSystem"` + SortOrder int `gorm:"column:sort_order;default:0" json:"sortOrder"` + Status int `gorm:"column:status;default:1" json:"status"` + CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"createdAt"` + UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updatedAt"` +} + +func (Role) TableName() string { + return "role" +} diff --git a/backend/model/role_menu_model.go b/backend/model/role_menu_model.go new file mode 100644 index 0000000..341a10e --- /dev/null +++ b/backend/model/role_menu_model.go @@ -0,0 +1,59 @@ +package model + +import ( + "context" + + "gorm.io/gorm" +) + +// RoleMenu 角色-菜单关联 +type RoleMenu struct { + Id int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` + RoleId int64 `gorm:"column:role_id;index" json:"roleId"` + MenuId int64 `gorm:"column:menu_id;index" json:"menuId"` +} + +func (RoleMenu) TableName() string { + return "role_menu" +} + +// RoleMenuFindByRoleId 获取角色的菜单ID列表 +func RoleMenuFindByRoleId(ctx context.Context, db *gorm.DB, roleId int64) ([]int64, error) { + var menuIds []int64 + err := db.WithContext(ctx).Model(&RoleMenu{}).Where("role_id = ?", roleId).Pluck("menu_id", &menuIds).Error + return menuIds, err +} + +// RoleMenuFindByRoleIds 获取多个角色的菜单ID列表(去重) +func RoleMenuFindByRoleIds(ctx context.Context, db *gorm.DB, roleIds []int64) ([]int64, error) { + var menuIds []int64 + if len(roleIds) == 0 { + return menuIds, nil + } + err := db.WithContext(ctx).Model(&RoleMenu{}).Where("role_id IN ?", roleIds).Distinct("menu_id").Pluck("menu_id", &menuIds).Error + return menuIds, err +} + +// RoleMenuSetForRole 全量设置角色的菜单(先删后插) +func RoleMenuSetForRole(ctx context.Context, db *gorm.DB, roleId int64, menuIds []int64) error { + return db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + // 删除旧关联 + if err := tx.Where("role_id = ?", roleId).Delete(&RoleMenu{}).Error; err != nil { + return err + } + // 插入新关联 + if len(menuIds) == 0 { + return nil + } + records := make([]RoleMenu, 0, len(menuIds)) + for _, menuId := range menuIds { + records = append(records, RoleMenu{RoleId: roleId, MenuId: menuId}) + } + return tx.Create(&records).Error + }) +} + +// RoleMenuDeleteByRoleId 删除角色的所有菜单关联 +func RoleMenuDeleteByRoleId(ctx context.Context, db *gorm.DB, roleId int64) error { + return db.WithContext(ctx).Where("role_id = ?", roleId).Delete(&RoleMenu{}).Error +} diff --git a/backend/model/role_model.go b/backend/model/role_model.go new file mode 100644 index 0000000..250c5d2 --- /dev/null +++ b/backend/model/role_model.go @@ -0,0 +1,60 @@ +package model + +import ( + "context" + "errors" + + "gorm.io/gorm" +) + +// RoleInsert 插入角色 +func RoleInsert(ctx context.Context, db *gorm.DB, role *Role) (int64, error) { + result := db.WithContext(ctx).Create(role) + if result.Error != nil { + return 0, result.Error + } + return role.Id, nil +} + +// RoleFindOne 根据ID查询角色 +func RoleFindOne(ctx context.Context, db *gorm.DB, id int64) (*Role, error) { + var role Role + result := db.WithContext(ctx).First(&role, id) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, ErrNotFound + } + return nil, result.Error + } + return &role, nil +} + +// RoleFindOneByCode 根据编码查询角色 +func RoleFindOneByCode(ctx context.Context, db *gorm.DB, code string) (*Role, error) { + var role Role + result := db.WithContext(ctx).Where("code = ?", code).First(&role) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, ErrNotFound + } + return nil, result.Error + } + return &role, nil +} + +// RoleFindAll 查询所有启用的角色 +func RoleFindAll(ctx context.Context, db *gorm.DB) ([]Role, error) { + var roles []Role + err := db.WithContext(ctx).Where("status = 1").Order("sort_order ASC, id ASC").Find(&roles).Error + return roles, err +} + +// RoleUpdate 更新角色 +func RoleUpdate(ctx context.Context, db *gorm.DB, role *Role) error { + return db.WithContext(ctx).Save(role).Error +} + +// RoleDelete 删除角色 +func RoleDelete(ctx context.Context, db *gorm.DB, id int64) error { + return db.WithContext(ctx).Delete(&Role{}, id).Error +} diff --git a/backend/model/user_organization_entity.go b/backend/model/user_organization_entity.go new file mode 100644 index 0000000..c605d3e --- /dev/null +++ b/backend/model/user_organization_entity.go @@ -0,0 +1,16 @@ +package model + +import "time" + +// UserOrganization 用户-机构-角色关联 +type UserOrganization struct { + Id int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` + UserId int64 `gorm:"column:user_id;index" json:"userId"` + OrgId int64 `gorm:"column:org_id;index" json:"orgId"` + RoleId int64 `gorm:"column:role_id" json:"roleId"` + CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"createdAt"` +} + +func (UserOrganization) TableName() string { + return "user_organization" +} diff --git a/backend/model/user_organization_model.go b/backend/model/user_organization_model.go new file mode 100644 index 0000000..19d2334 --- /dev/null +++ b/backend/model/user_organization_model.go @@ -0,0 +1,66 @@ +package model + +import ( + "context" + "errors" + + "gorm.io/gorm" +) + +// UserOrgInsert 添加用户-机构关联 +func UserOrgInsert(ctx context.Context, db *gorm.DB, uo *UserOrganization) (int64, error) { + result := db.WithContext(ctx).Create(uo) + if result.Error != nil { + return 0, result.Error + } + return uo.Id, nil +} + +// UserOrgFindOne 查询单条关联 +func UserOrgFindOne(ctx context.Context, db *gorm.DB, userId, orgId int64) (*UserOrganization, error) { + var uo UserOrganization + result := db.WithContext(ctx).Where("user_id = ? AND org_id = ?", userId, orgId).First(&uo) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, ErrNotFound + } + return nil, result.Error + } + return &uo, nil +} + +// UserOrgFindByUserId 获取用户的所有机构关联 +func UserOrgFindByUserId(ctx context.Context, db *gorm.DB, userId int64) ([]UserOrganization, error) { + var list []UserOrganization + err := db.WithContext(ctx).Where("user_id = ?", userId).Find(&list).Error + return list, err +} + +// UserOrgFindByOrgId 获取机构的所有成员关联 +func UserOrgFindByOrgId(ctx context.Context, db *gorm.DB, orgId int64) ([]UserOrganization, error) { + var list []UserOrganization + err := db.WithContext(ctx).Where("org_id = ?", orgId).Find(&list).Error + return list, err +} + +// UserOrgUpdate 更新关联(如改角色) +func UserOrgUpdate(ctx context.Context, db *gorm.DB, uo *UserOrganization) error { + return db.WithContext(ctx).Save(uo).Error +} + +// UserOrgDelete 删除关联 +func UserOrgDelete(ctx context.Context, db *gorm.DB, userId, orgId int64) error { + return db.WithContext(ctx).Where("user_id = ? AND org_id = ?", userId, orgId).Delete(&UserOrganization{}).Error +} + +// UserOrgDeleteByOrgId 删除机构的所有成员关联 +func UserOrgDeleteByOrgId(ctx context.Context, db *gorm.DB, orgId int64) error { + return db.WithContext(ctx).Where("org_id = ?", orgId).Delete(&UserOrganization{}).Error +} + +// UserOrgCountByOrgId 统计机构成员数 +func UserOrgCountByOrgId(ctx context.Context, db *gorm.DB, orgId int64) (int64, error) { + var count int64 + err := db.WithContext(ctx).Model(&UserOrganization{}).Where("org_id = ?", orgId).Count(&count).Error + return count, err +}