优化平台端租户端

This commit is contained in:
2026-09-09 00:30:44 +08:00
parent 672c22d9b6
commit 34b2449462
20 changed files with 847 additions and 42 deletions
+2 -1
View File
@@ -5,7 +5,8 @@ import "time"
// AdminRole 平台角色表 yz_system_admin_role
type AdminRole struct {
ID uint64 `orm:"column(id);pk;auto" json:"id"`
Cid uint8 `orm:"column(cid);default(1)" json:"cid"` // 1平台角色 2租户角色
TenantID uint64 `orm:"column(tenant_id);default(0)" json:"tenant_id"` // 租户ID:0=平台/全局,>0=具体租户(仅 cid=2 租户角色使用)
Cid uint8 `orm:"column(cid);default(1)" json:"cid"` // 1平台角色 2租户角色
Name string `orm:"column(name);size(32)" json:"name"`
Status uint8 `orm:"column(status);default(1)" json:"status"`
Rights *string `orm:"column(rights);type(text);null" json:"rights"`
+80
View File
@@ -0,0 +1,80 @@
package models
import (
"sync"
"github.com/beego/beego/v2/client/orm"
)
var adminRoleTenantColOnce sync.Once
// EnsureAdminRoleTenantColumn 为角色表补齐 tenant_id 列(历史库可能早于租户隔离特性建表)。
// 字段已存在时 MySQL 报 duplicate column,统一忽略,不阻断主流程。
func EnsureAdminRoleTenantColumn() {
if Orm == nil {
return
}
adminRoleTenantColOnce.Do(func() {
_, _ = Orm.Raw(`
ALTER TABLE yz_system_admin_role
ADD COLUMN tenant_id bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID 0-平台/全局 >0-具体租户'
`).Exec()
})
}
// EnsureDefaultTenantRoles 保证指定租户(cid=2)的默认角色齐全:
// - 租户管理员:全权限(rights 为空,见 permission.go 空权限即放行)
// - 部门负责人
// - 员工
//
// 默认角色按租户隔离:每个租户首次访问角色列表时补建自己的一套,互不影响。
// 缺失的自动插入;已存在(同名同 cid 同租户)的不动。任何失败均静默忽略不阻断主流程。
func EnsureDefaultTenantRoles(tid uint64) {
if Orm == nil || tid == 0 {
return
}
// 确保 tenant_id 列存在(兼容老表)
EnsureAdminRoleTenantColumn()
defaults := []string{"租户管理员", "部门负责人", "员工"}
for _, name := range defaults {
cnt, err := Orm.QueryTable(new(AdminRole)).
Filter("cid", 2).
Filter("tenant_id", tid).
Filter("name", name).
Count()
if err != nil {
continue
}
if cnt > 0 {
continue
}
role := &AdminRole{
TenantID: tid,
Cid: 2,
Name: name,
Status: 1,
Rights: nil, // 空权限 = 全权限(permission.go)
}
_, _ = Orm.Insert(role)
}
}
// GetTenantAdminRole 返回指定租户(cid=2)的「租户管理员」角色 ID。
// 角色不存在时先调用 EnsureDefaultTenantRoles 补建再查;任何失败返回 (0, err)。
// 普通租户(租户第一个账号)与租户管理员实为同一概念,均绑定此角色以获得 backend 全权限。
func GetTenantAdminRole(tid uint64) (uint64, error) {
if Orm == nil || tid == 0 {
return 0, orm.ErrNoRows
}
EnsureDefaultTenantRoles(tid)
var role AdminRole
if err := Orm.QueryTable(new(AdminRole)).
Filter("cid", 2).
Filter("tenant_id", tid).
Filter("name", "租户管理员").
One(&role); err != nil {
return 0, err
}
return role.ID, nil
}
+21 -1
View File
@@ -1,11 +1,15 @@
package models
import "time"
import (
"sync"
"time"
)
type SystemTenantUser struct {
ID uint64 `orm:"column(id);pk;auto" json:"id"`
Tid uint64 `orm:"column(tid)" json:"tid"`
Uid uint64 `orm:"column(uid)" json:"uid"`
GroupID uint64 `orm:"column(group_id);default(0)" json:"group_id"` // 角色ID:关联 yz_system_admin_role(id, cid=2);0=未分配(视为全权限)
Account *string `orm:"column(account);size(64);null" json:"account"`
Name *string `orm:"column(name);size(64);null" json:"name"`
Phone *string `orm:"column(phone);size(20);null" json:"phone"`
@@ -24,3 +28,19 @@ type SystemTenantUser struct {
func (m *SystemTenantUser) TableName() string {
return "yz_system_tenant_user"
}
var tenantUserGroupColOnce sync.Once
// EnsureTenantUserGroupColumn 为租户用户表补齐 group_id(角色)列。
// 历史库可能早于"用户-角色"特性建表,字段已存在时 MySQL 报 duplicate column,统一忽略。
func EnsureTenantUserGroupColumn() {
if Orm == nil {
return
}
tenantUserGroupColOnce.Do(func() {
_, _ = Orm.Raw(`
ALTER TABLE yz_system_tenant_user
ADD COLUMN group_id bigint unsigned NOT NULL DEFAULT 0 COMMENT '角色ID 关联 yz_system_admin_role(cid=2)'
`).Exec()
})
}