知识库增加租户隔离

This commit is contained in:
2025-11-05 17:50:02 +08:00
parent b00463cb14
commit 9c67793fc3
19 changed files with 473 additions and 87 deletions
+4 -2
View File
@@ -91,7 +91,8 @@ func (c *AuthController) Login() {
"avatar": user.Avatar,
"nickname": user.Nickname,
"tenant_id": user.TenantId,
"type": "user", // 标识是用户登录
"role": user.Role, // 角色ID
"type": "user", // 标识是用户登录
}
} else if employee != nil {
// 员工登录
@@ -107,7 +108,8 @@ func (c *AuthController) Login() {
"tenant_id": employee.TenantId,
"department_id": employee.DepartmentId,
"position_id": employee.PositionId,
"type": "employee", // 标识是员工登录
"role": employee.Role, // 角色ID
"type": "employee", // 标识是员工登录
}
} else {
c.Data["json"] = map[string]interface{}{
+55 -37
View File
@@ -61,18 +61,21 @@ func (c *EmployeeController) GetTenantEmployees() {
employeeList := make([]map[string]interface{}, 0)
for _, emp := range employees {
employeeList = append(employeeList, map[string]interface{}{
"id": emp.Id,
"tenant_id": emp.TenantId,
"employee_no": emp.EmployeeNo,
"name": emp.Name,
"phone": emp.Phone,
"email": emp.Email,
"id": emp.Id,
"tenant_id": emp.TenantId,
"employee_no": emp.EmployeeNo,
"name": emp.Name,
"phone": emp.Phone,
"email": emp.Email,
"department_id": emp.DepartmentId,
"position_id": emp.PositionId,
"bank_name": emp.BankName,
"bank_account": emp.BankAccount,
"status": emp.Status,
"create_time": emp.CreateTime,
"position_id": emp.PositionId,
"role": emp.Role,
"bank_name": emp.BankName,
"bank_account": emp.BankAccount,
"status": emp.Status,
"create_time": emp.CreateTime,
"last_login_time": emp.LastLoginTime,
"last_login_ip": emp.LastLoginIp,
})
}
@@ -109,24 +112,27 @@ func (c *EmployeeController) GetEmployeeInfo() {
return
}
c.Data["json"] = map[string]interface{}{
"code": 0,
"message": "获取员工信息成功",
"data": map[string]interface{}{
"id": employee.Id,
"tenant_id": employee.TenantId,
"employee_no": employee.EmployeeNo,
"name": employee.Name,
"phone": employee.Phone,
"email": employee.Email,
"department_id": employee.DepartmentId,
"position_id": employee.PositionId,
"bank_name": employee.BankName,
"bank_account": employee.BankAccount,
"status": employee.Status,
"create_time": employee.CreateTime,
},
}
c.Data["json"] = map[string]interface{}{
"code": 0,
"message": "获取员工信息成功",
"data": map[string]interface{}{
"id": employee.Id,
"tenant_id": employee.TenantId,
"employee_no": employee.EmployeeNo,
"name": employee.Name,
"phone": employee.Phone,
"email": employee.Email,
"department_id": employee.DepartmentId,
"position_id": employee.PositionId,
"role": employee.Role,
"bank_name": employee.BankName,
"bank_account": employee.BankAccount,
"status": employee.Status,
"create_time": employee.CreateTime,
"last_login_time": employee.LastLoginTime,
"last_login_ip": employee.LastLoginIp,
},
}
c.ServeJSON()
}
@@ -141,9 +147,10 @@ func (c *EmployeeController) AddEmployee() {
Email string `json:"email"`
DepartmentId int `json:"department_id"`
PositionId int `json:"position_id"`
Role int `json:"role"`
BankName string `json:"bank_name"`
BankAccount string `json:"bank_account"`
Status int8 `json:"status"`
Status int `json:"status"` // 使用int,前端传递number会自动转换
}
err := json.Unmarshal(c.Ctx.Input.RequestBody, &employeeData)
@@ -165,16 +172,25 @@ func (c *EmployeeController) AddEmployee() {
Email: employeeData.Email,
DepartmentId: employeeData.DepartmentId,
PositionId: employeeData.PositionId,
Role: employeeData.Role,
BankName: employeeData.BankName,
BankAccount: employeeData.BankAccount,
Status: employeeData.Status,
Status: int8(employeeData.Status), // 转换为int8
}
// 如果没有指定租户ID,从当前登录用户获取(需要JWT中间件支持)
// 这里暂时使用传入的tenant_id,如果为0则使用默认值
// 如果没有指定租户ID,从JWT token中获取
if employee.TenantId == 0 {
// 可以从JWT token中获取租户ID,这里暂时设为1作为默认值
employee.TenantId = 1
if tenantId, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantId > 0 {
employee.TenantId = tenantId
} else {
c.Data["json"] = map[string]interface{}{
"code": 1,
"message": "租户ID不能为空",
"data": nil,
}
c.ServeJSON()
return
}
}
// 默认密码
@@ -220,9 +236,10 @@ func (c *EmployeeController) UpdateEmployee() {
Email string `json:"email"`
DepartmentId int `json:"department_id"`
PositionId int `json:"position_id"`
Role int `json:"role"`
BankName string `json:"bank_name"`
BankAccount string `json:"bank_account"`
Status int8 `json:"status"`
Status int `json:"status"` // 使用int,前端传递number会自动转换
}
err = json.Unmarshal(c.Ctx.Input.RequestBody, &updateData)
@@ -254,9 +271,10 @@ func (c *EmployeeController) UpdateEmployee() {
employee.Email = updateData.Email
employee.DepartmentId = updateData.DepartmentId
employee.PositionId = updateData.PositionId
employee.Role = updateData.Role
employee.BankName = updateData.BankName
employee.BankAccount = updateData.BankAccount
employee.Status = updateData.Status
employee.Status = int8(updateData.Status) // 转换为int8
if err := models.UpdateEmployee(employee); err != nil {
c.Data["json"] = map[string]interface{}{
+84 -10
View File
@@ -23,9 +23,18 @@ func (c *KnowledgeController) List() {
categoryId, _ := c.GetInt("categoryId", 0)
share, _ := c.GetInt8("share", -1) // Default -1 to query all
keyword := c.GetString("keyword", "")
// 获取租户ID(如果是员工登录,从JWT token中获取)
tenantId := 0
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
// 检查是否是员工登录(type === "employee"
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
tenantId = tenantIdVal
}
}
// Use share in the query
knowledges, total, err := models.GetAllKnowledge(page, pageSize, status, categoryId, share, keyword)
knowledges, total, err := models.GetAllKnowledge(page, pageSize, status, categoryId, share, keyword, tenantId)
if err != nil {
c.Data["json"] = map[string]interface{}{
"code": 1,
@@ -62,8 +71,17 @@ func (c *KnowledgeController) Detail() {
c.ServeJSON()
return
}
// 获取租户ID(如果是员工登录,从JWT token中获取)
tenantId := 0
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
// 检查是否是员工登录(type === "employee"
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
tenantId = tenantIdVal
}
}
knowledge, err := models.GetKnowledgeById(id)
knowledge, err := models.GetKnowledgeById(id, tenantId)
if err != nil {
c.Data["json"] = map[string]interface{}{
"code": 1,
@@ -112,6 +130,14 @@ func (c *KnowledgeController) Create() {
// Add share parsing (default 0 for personal)
share, _ := c.GetInt8("share", 0)
knowledge.Share = share
// 获取租户ID(如果是员工登录,从JWT token中获取并设置)
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
// 检查是否是员工登录(type === "employee"
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
knowledge.TenantId = tenantIdVal
}
}
id, err := models.AddKnowledge(&knowledge)
if err != nil {
@@ -158,12 +184,17 @@ func (c *KnowledgeController) Update() {
c.ServeJSON()
return
}
// 获取租户ID(如果是员工登录,从JWT token中获取)
tenantId := 0
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
// 检查是否是员工登录(type === "employee"
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
tenantId = tenantIdVal
}
}
// Add share parsing
share, _ := c.GetInt8("share", 0) // Default 0 if not provided
knowledge.Share = share
err = models.UpdateKnowledge(knowledge.Id, &knowledge)
err = models.UpdateKnowledge(knowledge.Id, &knowledge, tenantId)
if err != nil {
c.Data["json"] = map[string]interface{}{
"code": 1,
@@ -216,8 +247,17 @@ func (c *KnowledgeController) Delete() {
if deleteBy == "" {
deleteBy = "system" // 默认值
}
// 获取租户ID(如果是员工登录,从JWT token中获取)
tenantId := 0
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
// 检查是否是员工登录(type === "employee"
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
tenantId = tenantIdVal
}
}
err = models.DeleteKnowledge(int(id), deleteBy)
err = models.DeleteKnowledge(int(id), deleteBy, tenantId)
if err != nil {
c.Data["json"] = map[string]interface{}{
"code": 1,
@@ -239,7 +279,16 @@ func (c *KnowledgeController) Delete() {
// GetCategories 获取分类列表
// @router /api/knowledge/categories [get]
func (c *KnowledgeController) GetCategories() {
categories, err := models.GetAllCategories()
// 获取租户ID(如果是员工登录,从JWT token中获取)
tenantId := 0
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
// 检查是否是员工登录(type === "employee"
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
tenantId = tenantIdVal
}
}
categories, err := models.GetAllCategories(tenantId)
if err != nil {
c.Data["json"] = map[string]interface{}{
"code": 1,
@@ -275,7 +324,16 @@ func (c *KnowledgeController) GetCategories() {
// GetTags 获取标签列表
// @router /api/knowledge/tags [get]
func (c *KnowledgeController) GetTags() {
tags, err := models.GetAllTags()
// 获取租户ID(如果是员工登录,从JWT token中获取)
tenantId := 0
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
// 检查是否是员工登录(type === "employee"
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
tenantId = tenantIdVal
}
}
tags, err := models.GetAllTags(tenantId)
if err != nil {
c.Data["json"] = map[string]interface{}{
"code": 1,
@@ -322,6 +380,14 @@ func (c *KnowledgeController) AddCategory() {
c.ServeJSON()
return
}
// 获取租户ID(如果是员工登录,从JWT token中获取并设置)
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
// 检查是否是员工登录(type === "employee"
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
category.TenantId = tenantIdVal
}
}
// 不处理id,直接添加,表自动递增
_, err = models.AddCategory(&category)
@@ -357,6 +423,14 @@ func (c *KnowledgeController) AddTag() {
c.ServeJSON()
return
}
// 获取租户ID(如果是员工登录,从JWT token中获取并设置)
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
// 检查是否是员工登录(type === "employee"
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
tag.TenantId = tenantIdVal
}
}
// 判断是添加还是更新
if tag.TagId > 0 {
+32
View File
@@ -34,6 +34,38 @@ func (c *MenuController) GetAllMenus() {
c.ServeJSON()
}
// GetTenantMenus 根据角色获取租户菜单(只返回该角色有权限的菜单)
// @router /menus/tenant/:roleId [get]
func (c *MenuController) GetTenantMenus() {
roleId, err := c.GetInt(":roleId")
if err != nil || roleId <= 0 {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "角色ID无效",
"data": nil,
}
c.ServeJSON()
return
}
menus, err := models.GetTenantMenus(roleId)
if err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "获取菜单失败: " + err.Error(),
"data": nil,
}
} else {
c.Data["json"] = map[string]interface{}{
"success": true,
"message": "获取菜单成功",
"data": menus,
}
}
c.ServeJSON()
}
// CreateMenu 创建新菜单
func (c *MenuController) CreateMenu() {
var menu models.Menu
+2
View File
@@ -77,6 +77,8 @@ func (c *UserController) GetTenantUsers() {
"tenant_id": user.TenantId,
"status": user.Status,
"role": user.Role,
"department_id": user.DepartmentId,
"position_id": user.PositionId,
"last_login_time": user.LastLoginTime,
"last_login_ip": user.LastLoginIp,
})
+8
View File
@@ -64,5 +64,13 @@ func JWTAuthMiddleware() web.FilterFunc {
ctx.Input.SetData("userId", claims.UserID)
ctx.Input.SetData("username", claims.Username)
ctx.Input.SetData("tenantId", claims.TenantId)
// 判断用户类型:检查userId是否在员工表中
// 如果userId在yz_tenant_employees表中存在,则为员工登录;否则为用户登录
userType := "user"
if models.IsEmployee(claims.UserID) {
userType = "employee"
}
ctx.Input.SetData("userType", userType)
}
}
+17 -1
View File
@@ -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
View File
@@ -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, &params, "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
}
+68
View File
@@ -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
}
+1
View File
@@ -249,6 +249,7 @@ func init() {
beego.Router("/api/menu/:id", &controllers.MenuController{}, "put:UpdateMenu")
beego.Router("/api/menu/:id", &controllers.MenuController{}, "delete:DeleteMenu")
beego.Router("/api/menu/status/:id", &controllers.MenuController{}, "patch:UpdateMenuStatus")
beego.Router("/api/menus/tenant/:roleId", &controllers.MenuController{}, "get:GetTenantMenus")
// 程序分类路由 - 自动映射到 /api/programcategory/*
beego.AutoRouter(&controllers.ProgramCategoryController{})