141 lines
4.4 KiB
Go
141 lines
4.4 KiB
Go
|
|
package models
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"encoding/json"
|
|||
|
|
"errors"
|
|||
|
|
"log"
|
|||
|
|
"os"
|
|||
|
|
"strings"
|
|||
|
|
|
|||
|
|
"git.apinb.com/bsm-sdk/core/types"
|
|||
|
|
"git.apinb.com/bsm-sdk/core/utils"
|
|||
|
|
"gorm.io/gorm"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// DefaultFilePath 相对进程工作目录,与服务启动时读取配置方式一致
|
|||
|
|
const DefaultFilePath = "etc/menu.json"
|
|||
|
|
|
|||
|
|
// File 与 etc/menu_structure.json 根结构一致
|
|||
|
|
type File struct {
|
|||
|
|
Menus []Node `json:"menus"`
|
|||
|
|
TotalLevel1 int `json:"total_level1"`
|
|||
|
|
TotalLevel2 int `json:"total_level2"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Node 菜单节点(可嵌套 children)
|
|||
|
|
type Node struct {
|
|||
|
|
Title string `json:"title"`
|
|||
|
|
TitleEn string `json:"title_en"`
|
|||
|
|
Code string `json:"code"`
|
|||
|
|
Description string `json:"description"`
|
|||
|
|
MenuPath string `json:"menu_path"`
|
|||
|
|
Type int8 `json:"type"`
|
|||
|
|
SortKey int8 `json:"sort_key"`
|
|||
|
|
IsWebPage bool `json:"is_web_page"`
|
|||
|
|
IsNewTab bool `json:"is_new_tab"`
|
|||
|
|
IsFull bool `json:"is_full"`
|
|||
|
|
HideMenu bool `json:"hide_menu"`
|
|||
|
|
WebURL string `json:"web_url"`
|
|||
|
|
Component string `json:"component"`
|
|||
|
|
Children []Node `json:"children"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Load 读取并解析 path
|
|||
|
|
func Load(path string) (*File, error) {
|
|||
|
|
raw, err := os.ReadFile(path)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
var f File
|
|||
|
|
if err := json.Unmarshal(raw, &f); err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
return &f, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func buildPermissions(tx *gorm.DB, appID uint) ([]MgtPermission, error) {
|
|||
|
|
mf, err := Load(DefaultFilePath)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
if len(mf.Menus) == 0 {
|
|||
|
|
return nil, errors.New("menu is empty")
|
|||
|
|
}
|
|||
|
|
var out []MgtPermission
|
|||
|
|
if err := walkMenuTree(tx, appID, 0, mf.Menus, &out); err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
log.Printf("已从 %s 载入 %d 条权限(含子级)", DefaultFilePath, len(out))
|
|||
|
|
return out, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func walkMenuTree(tx *gorm.DB, appID uint, parentID uint, nodes []Node, out *[]MgtPermission) error {
|
|||
|
|
for i := range nodes {
|
|||
|
|
p, err := upsertMenuPermissionFromJSON(tx, appID, parentID, nodes[i])
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
*out = append(*out, p)
|
|||
|
|
if len(nodes[i].Children) > 0 {
|
|||
|
|
if err := walkMenuTree(tx, appID, p.ID, nodes[i].Children, out); err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func upsertMenuPermissionFromJSON(tx *gorm.DB, appID, parentID uint, n Node) (MgtPermission, error) {
|
|||
|
|
code := strings.TrimSpace(n.Code)
|
|||
|
|
if code == "" {
|
|||
|
|
code = "menu_" + strings.ReplaceAll(utils.UUID(), "-", "")
|
|||
|
|
}
|
|||
|
|
typ := n.Type
|
|||
|
|
if typ == 0 {
|
|||
|
|
typ = 1
|
|||
|
|
}
|
|||
|
|
p := MgtPermission{
|
|||
|
|
Std_IICUDS: types.Std_IICUDS{Identity: utils.UUID(), Status: 1},
|
|||
|
|
Title: n.Title,
|
|||
|
|
TitleEn: n.TitleEn,
|
|||
|
|
Code: code,
|
|||
|
|
Description: n.Description,
|
|||
|
|
Appid: appID,
|
|||
|
|
ParentID: parentID,
|
|||
|
|
MenuPath: n.MenuPath,
|
|||
|
|
MenuIcon: "",
|
|||
|
|
SortKey: n.SortKey,
|
|||
|
|
Type: typ,
|
|||
|
|
Component: n.Component,
|
|||
|
|
IsWebPage: n.IsWebPage,
|
|||
|
|
IsNewTab: n.IsNewTab,
|
|||
|
|
IsFull: n.IsFull,
|
|||
|
|
HideMenu: n.HideMenu,
|
|||
|
|
WebUrl: n.WebURL,
|
|||
|
|
}
|
|||
|
|
var existingPmn MgtPermission
|
|||
|
|
err := tx.Model(&MgtPermission{}).Where("code = ? AND app_id = ?", p.Code, appID).First(&existingPmn).Error
|
|||
|
|
if err == gorm.ErrRecordNotFound {
|
|||
|
|
if err := tx.Create(&p).Error; err != nil {
|
|||
|
|
return p, err
|
|||
|
|
}
|
|||
|
|
return p, nil
|
|||
|
|
}
|
|||
|
|
if err != nil {
|
|||
|
|
return p, err
|
|||
|
|
}
|
|||
|
|
p.ID = existingPmn.ID
|
|||
|
|
return p, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func builtinManagementMenuTemplates() []MgtPermission {
|
|||
|
|
return []MgtPermission{
|
|||
|
|
{Title: "系统管理", TitleEn: "System Management", Code: "system:management", Description: "系统管理菜单", MenuPath: "/system", MenuIcon: "setting", SortKey: 1, Type: 1},
|
|||
|
|
{Title: "用户管理", TitleEn: "User Management", Code: "user:management", Description: "用户管理菜单", MenuPath: "/system/user", MenuIcon: "user", SortKey: 2, Type: 1},
|
|||
|
|
{Title: "角色管理", TitleEn: "Role Management", Code: "role:management", Description: "角色管理菜单", MenuPath: "/system/role", MenuIcon: "team", SortKey: 3, Type: 1},
|
|||
|
|
{Title: "权限管理", TitleEn: "Permission Management", Code: "permission:management", Description: "权限管理菜单", MenuPath: "/system/permission", MenuIcon: "safety", SortKey: 4, Type: 1},
|
|||
|
|
{Title: "应用管理", TitleEn: "Application Management", Code: "application:management", Description: "应用管理菜单", MenuPath: "/system/application", MenuIcon: "appstore", SortKey: 5, Type: 1},
|
|||
|
|
{Title: "部门管理", TitleEn: "Department Management", Code: "department:management", Description: "部门管理菜单", MenuPath: "/system/department", MenuIcon: "apartment", SortKey: 6, Type: 1},
|
|||
|
|
}
|
|||
|
|
}
|