知识库增加租户隔离
This commit is contained in:
@@ -21,6 +21,7 @@ type Employee struct {
|
||||
Email string `orm:"size(100);null" json:"email"`
|
||||
DepartmentId int `orm:"column(department_id);null;default(0)" json:"department_id"`
|
||||
PositionId int `orm:"column(position_id);null;default(0)" json:"position_id"`
|
||||
Role int `orm:"column(role);null;default(0)" json:"role"` // 角色ID
|
||||
BankName string `orm:"column(bank_name);size(100);null" json:"bank_name"`
|
||||
BankAccount string `orm:"column(bank_account);size(50);null" json:"bank_account"`
|
||||
Password string `orm:"size(255);null" json:"-"` // 不返回给前端
|
||||
@@ -121,7 +122,7 @@ func AddEmployee(employee *Employee, defaultPassword string) (int64, error) {
|
||||
// UpdateEmployee 更新员工信息
|
||||
func UpdateEmployee(employee *Employee) error {
|
||||
o := orm.NewOrm()
|
||||
_, err := o.Update(employee, "employee_no", "name", "phone", "email", "department_id", "position_id", "bank_name", "bank_account", "status", "update_time")
|
||||
_, err := o.Update(employee, "employee_no", "name", "phone", "email", "department_id", "position_id", "role", "bank_name", "bank_account", "status", "update_time")
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -240,3 +241,18 @@ func GetAllEmployees() ([]*Employee, error) {
|
||||
return employees, err
|
||||
}
|
||||
|
||||
// IsEmployee 检查指定的ID是否是员工(用于判断登录类型)
|
||||
func IsEmployee(id int) bool {
|
||||
o := orm.NewOrm()
|
||||
employee := &Employee{Id: id}
|
||||
err := o.Read(employee)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
// 检查是否已删除
|
||||
if employee.DeleteTime != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
+53
-12
@@ -9,6 +9,7 @@ import (
|
||||
// Knowledge 知识库模型
|
||||
type Knowledge struct {
|
||||
Id int `orm:"column(knowledge_id);pk;auto" json:"id"`
|
||||
TenantId int `orm:"column(tenant_id);default(0)" json:"tenantId"`
|
||||
Title string `orm:"column(title);size(200)" json:"title"`
|
||||
CategoryId int `orm:"column(category_id);default(0);null" json:"categoryId"`
|
||||
CategoryName string `orm:"-" json:"categoryName"` // 不映射到数据库,从联查获取
|
||||
@@ -39,6 +40,7 @@ func (k *Knowledge) TableName() string {
|
||||
// KnowledgeCategory 知识库分类模型
|
||||
type KnowledgeCategory struct {
|
||||
CategoryId int `orm:"column(category_id);pk;auto" json:"categoryId"`
|
||||
TenantId int `orm:"column(tenant_id);default(0)" json:"tenantId"`
|
||||
CategoryName string `orm:"column(category_name);size(100)" json:"categoryName"`
|
||||
CategoryDesc string `orm:"column(category_desc);size(500);null" json:"categoryDesc"`
|
||||
ParentId int `orm:"column(parent_id);default(0)" json:"parentId"`
|
||||
@@ -55,7 +57,8 @@ func (kc *KnowledgeCategory) TableName() string {
|
||||
// KnowledgeTag 知识库标签模型
|
||||
type KnowledgeTag struct {
|
||||
TagId int `orm:"column(tag_id);pk;auto" json:"tagId"`
|
||||
TagName string `orm:"column(tag_name);size(50);unique" json:"tagName"`
|
||||
TenantId int `orm:"column(tenant_id);default(0)" json:"tenantId"`
|
||||
TagName string `orm:"column(tag_name);size(50)" json:"tagName"`
|
||||
TagColor string `orm:"column(tag_color);size(20);null" json:"tagColor"`
|
||||
TagBackground string `orm:"column(tag_background);size(20);null" json:"tagBackground"`
|
||||
UsageCount int `orm:"column(usage_count);default(0)" json:"usageCount"`
|
||||
@@ -76,7 +79,7 @@ func AddKnowledge(k *Knowledge) (int64, error) {
|
||||
}
|
||||
|
||||
// GetKnowledgeById 根据ID获取知识详情(使用联查获取分类名称)
|
||||
func GetKnowledgeById(id int) (*Knowledge, error) {
|
||||
func GetKnowledgeById(id int, tenantId int) (*Knowledge, error) {
|
||||
o := orm.NewOrm()
|
||||
|
||||
// 使用联查获取分类名称(只查询未删除的记录)
|
||||
@@ -86,6 +89,13 @@ func GetKnowledgeById(id int) (*Knowledge, error) {
|
||||
LEFT JOIN yz_knowledge_category c ON k.category_id = c.category_id
|
||||
WHERE k.knowledge_id = ? AND k.delete_time IS NULL
|
||||
`
|
||||
params := []interface{}{id}
|
||||
|
||||
// 如果tenantId > 0,添加租户过滤
|
||||
if tenantId > 0 {
|
||||
querySQL += " AND k.tenant_id = ?"
|
||||
params = append(params, tenantId)
|
||||
}
|
||||
|
||||
var result struct {
|
||||
Id int `orm:"column(knowledge_id)"`
|
||||
@@ -108,7 +118,7 @@ func GetKnowledgeById(id int) (*Knowledge, error) {
|
||||
UpdateBy string `orm:"column(update_by)"`
|
||||
}
|
||||
|
||||
err := o.Raw(querySQL, id).QueryRow(&result)
|
||||
err := o.Raw(querySQL, params...).QueryRow(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -165,11 +175,17 @@ func addCondition(where *string, params *[]interface{}, cond string, val interfa
|
||||
}
|
||||
|
||||
// GetAllKnowledge (simplified: direct mapping to LightKnowledge, no separate struct or loop)
|
||||
func GetAllKnowledge(page, pageSize int, status int8, categoryId int, share int8, keyword string) ([]*LightKnowledge, int64, error) {
|
||||
func GetAllKnowledge(page, pageSize int, status int8, categoryId int, share int8, keyword string, tenantId int) ([]*LightKnowledge, int64, error) {
|
||||
o := orm.NewOrm()
|
||||
|
||||
whereSQL := "delete_time IS NULL"
|
||||
params := []interface{}{}
|
||||
|
||||
// 如果tenantId > 0,添加租户过滤
|
||||
if tenantId > 0 {
|
||||
whereSQL += " AND k.tenant_id = ?"
|
||||
params = append(params, tenantId)
|
||||
}
|
||||
|
||||
addCondition(&whereSQL, ¶ms, "status = ?", func() interface{} {
|
||||
if status >= 0 {
|
||||
@@ -197,7 +213,7 @@ func GetAllKnowledge(page, pageSize int, status int8, categoryId int, share int8
|
||||
}())
|
||||
|
||||
var total int64
|
||||
err := o.Raw("SELECT COUNT(*) FROM yz_knowledge WHERE "+whereSQL, params).QueryRow(&total)
|
||||
err := o.Raw("SELECT COUNT(*) FROM yz_knowledge k WHERE "+whereSQL, params).QueryRow(&total)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
@@ -217,13 +233,18 @@ func GetAllKnowledge(page, pageSize int, status int8, categoryId int, share int8
|
||||
}
|
||||
|
||||
// UpdateKnowledge 更新知识
|
||||
func UpdateKnowledge(id int, k *Knowledge) error {
|
||||
func UpdateKnowledge(id int, k *Knowledge, tenantId int) error {
|
||||
o := orm.NewOrm()
|
||||
knowledge := &Knowledge{Id: id}
|
||||
err := o.Read(knowledge)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 如果tenantId > 0,验证租户ID是否匹配
|
||||
if tenantId > 0 && knowledge.TenantId != tenantId {
|
||||
return orm.ErrNoRows // 返回无记录错误,表示该知识不属于当前租户
|
||||
}
|
||||
|
||||
// 更新字段
|
||||
knowledge.Title = k.Title
|
||||
@@ -234,22 +255,28 @@ func UpdateKnowledge(id int, k *Knowledge) error {
|
||||
knowledge.Summary = k.Summary
|
||||
knowledge.CoverUrl = k.CoverUrl
|
||||
knowledge.Status = k.Status
|
||||
knowledge.Share = k.Share
|
||||
knowledge.IsRecommend = k.IsRecommend
|
||||
knowledge.IsTop = k.IsTop
|
||||
knowledge.UpdateBy = k.UpdateBy
|
||||
|
||||
_, err = o.Update(knowledge, "title", "category_id", "tags", "author", "content", "summary", "cover_url", "status", "is_recommend", "is_top", "update_by", "update_time")
|
||||
_, err = o.Update(knowledge, "title", "category_id", "tags", "author", "content", "summary", "cover_url", "status", "share", "is_recommend", "is_top", "update_by", "update_time")
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteKnowledge 软删除知识
|
||||
func DeleteKnowledge(id int, deleteBy string) error {
|
||||
func DeleteKnowledge(id int, deleteBy string, tenantId int) error {
|
||||
o := orm.NewOrm()
|
||||
knowledge := &Knowledge{Id: id}
|
||||
err := o.Read(knowledge)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 如果tenantId > 0,验证租户ID是否匹配
|
||||
if tenantId > 0 && knowledge.TenantId != tenantId {
|
||||
return orm.ErrNoRows // 返回无记录错误,表示该知识不属于当前租户
|
||||
}
|
||||
|
||||
// 执行软删除:设置 delete_time 和 delete_by
|
||||
_, err = o.Raw("UPDATE yz_knowledge SET delete_time = ?, delete_by = ? WHERE knowledge_id = ?", time.Now(), deleteBy, id).Exec()
|
||||
@@ -257,10 +284,17 @@ func DeleteKnowledge(id int, deleteBy string) error {
|
||||
}
|
||||
|
||||
// GetAllCategories 获取所有分类
|
||||
func GetAllCategories() ([]*KnowledgeCategory, error) {
|
||||
func GetAllCategories(tenantId int) ([]*KnowledgeCategory, error) {
|
||||
o := orm.NewOrm()
|
||||
qs := o.QueryTable("yz_knowledge_category")
|
||||
|
||||
// 如果tenantId > 0,添加租户过滤
|
||||
if tenantId > 0 {
|
||||
qs = qs.Filter("tenant_id", tenantId)
|
||||
}
|
||||
|
||||
var categories []*KnowledgeCategory
|
||||
_, err := o.QueryTable("yz_knowledge_category").OrderBy("sort_order").All(&categories)
|
||||
_, err := qs.OrderBy("sort_order").All(&categories)
|
||||
return categories, err
|
||||
}
|
||||
|
||||
@@ -273,10 +307,17 @@ func GetCategoryById(id int) (*KnowledgeCategory, error) {
|
||||
}
|
||||
|
||||
// GetAllTags 获取所有标签
|
||||
func GetAllTags() ([]*KnowledgeTag, error) {
|
||||
func GetAllTags(tenantId int) ([]*KnowledgeTag, error) {
|
||||
o := orm.NewOrm()
|
||||
qs := o.QueryTable("yz_knowledge_tags")
|
||||
|
||||
// 如果tenantId > 0,添加租户过滤
|
||||
if tenantId > 0 {
|
||||
qs = qs.Filter("tenant_id", tenantId)
|
||||
}
|
||||
|
||||
var tags []*KnowledgeTag
|
||||
_, err := o.QueryTable("yz_knowledge_tags").All(&tags)
|
||||
_, err := qs.All(&tags)
|
||||
return tags, err
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
@@ -96,3 +97,70 @@ func DeleteMenu(id int) error {
|
||||
_, err := o.Update(&menu, "DeleteTime")
|
||||
return err
|
||||
}
|
||||
|
||||
// GetTenantMenus 根据角色ID获取租户菜单(只返回该角色有权限的菜单,且只返回页面菜单menu_type=1)
|
||||
func GetTenantMenus(roleId int) ([]map[string]interface{}, error) {
|
||||
o := orm.NewOrm()
|
||||
|
||||
// 如果角色ID为0或无效,返回空列表
|
||||
if roleId <= 0 {
|
||||
return []map[string]interface{}{}, nil
|
||||
}
|
||||
|
||||
// 1. 从yz_role_menus表获取该角色的所有菜单ID
|
||||
var menuIds []int
|
||||
_, err := o.Raw("SELECT DISTINCT menu_id FROM yz_role_menus WHERE role_id = ?", roleId).QueryRows(&menuIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 如果没有权限,返回空列表
|
||||
if len(menuIds) == 0 {
|
||||
return []map[string]interface{}{}, nil
|
||||
}
|
||||
|
||||
// 2. 构建IN查询的占位符
|
||||
placeholders := make([]string, len(menuIds))
|
||||
args := make([]interface{}, len(menuIds)+1)
|
||||
for i, id := range menuIds {
|
||||
placeholders[i] = "?"
|
||||
args[i] = id
|
||||
}
|
||||
args[len(menuIds)] = 1 // menu_type=1 表示页面菜单
|
||||
|
||||
// 3. 查询菜单(只返回menu_type=1的页面菜单,且未删除的)
|
||||
query := "SELECT id, name, path, parent_id, icon, `order`, status, component_path, is_external, external_url, menu_type, permission " +
|
||||
"FROM yz_menus " +
|
||||
"WHERE id IN (" + strings.Join(placeholders, ",") + ") " +
|
||||
"AND delete_time IS NULL " +
|
||||
"AND menu_type = ? " +
|
||||
"ORDER BY `order`, id"
|
||||
|
||||
var menus []*Menu
|
||||
_, err = o.Raw(query, args...).QueryRows(&menus)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 4. 转换为map格式
|
||||
result := make([]map[string]interface{}, 0, len(menus))
|
||||
for _, m := range menus {
|
||||
item := map[string]interface{}{
|
||||
"id": m.Id,
|
||||
"name": m.Name,
|
||||
"path": m.Path,
|
||||
"parentId": m.ParentId,
|
||||
"icon": m.Icon,
|
||||
"order": m.Order,
|
||||
"status": m.Status,
|
||||
"componentPath": m.ComponentPath,
|
||||
"isExternal": m.IsExternal,
|
||||
"externalUrl": m.ExternalUrl,
|
||||
"menuType": m.MenuType,
|
||||
"permission": m.Permission,
|
||||
}
|
||||
result = append(result, item)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user