chore: 初始开源发布
iotlcm-admin-svr:管理后台服务。 - Go module:iotlcm → git.5iot.com/iotlcm-public/iotlcm-admin-svr(729 文件) - 凭据与地址脱敏:JWT signingKey(含代码里的 MustGet 默认值)、 MySQL DSN、Redis 口令、告警邮件发件人邮箱全部改为占位; 私网 IP → 文档地址段;库名 xiujie_admin → iotlcm - 真实手机号/邮箱 → 合法 11 位编造号 / example.com - 移除内部资产:CI 触发器、过时 DDL(sql/db_iotlcm.sql)、 私有依赖 go get 行、明文 registry 登录口令 - 启动 banner 统一 IOTLCM 方块字 + 社区惯例署名 - Dockerfile 改用公共基础镜像 - 拼错的 RADEME.md → README.md,README 重写 - 需要真实数据库的用例改为可用 IOTLCM_TEST_WITH_DB=1 显式启用 - 补 Apache-2.0 LICENSE,LF 行尾 + .gitattributes 数据库 schema 不随本仓发布(生产 DDL 已过时),README 已说明。
This commit is contained in:
@@ -0,0 +1,508 @@
|
||||
// package system
|
||||
// @Link https://github.com/xiujiecn/xiu-admin
|
||||
// @Copyright Copyright (c) 2025 LiXiujie
|
||||
// @Author Lxj <li@xiujie.cn>
|
||||
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
v1 "git.5iot.com/iotlcm-public/iotlcm-admin-svr/api/system/v1"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/consts"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/dao"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/contexts"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/event"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/rolepolicy"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/xgorm/handler"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model/entity"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/service"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
type sSysMenu struct {
|
||||
}
|
||||
|
||||
func NewSysMenu() *sSysMenu {
|
||||
return &sSysMenu{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
service.RegisterSysMenu(NewSysMenu())
|
||||
}
|
||||
|
||||
func (s *sSysMenu) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {
|
||||
if len(option) == 0 {
|
||||
option = append(option, &handler.Option{
|
||||
FilterTenant: false,
|
||||
FilterAuth: false,
|
||||
})
|
||||
}
|
||||
return handler.Model(dao.SysMenu.Ctx(ctx), option...)
|
||||
}
|
||||
|
||||
func (s *sSysMenu) ModelQuery(ctx context.Context, option ...*handler.Option) *gdb.Model {
|
||||
if len(option) == 0 {
|
||||
option = append(option, &handler.Option{
|
||||
FilterTenant: false,
|
||||
FilterAuth: false,
|
||||
})
|
||||
}
|
||||
return handler.Model(service.MemoryDB().DB(ctx).Ctx(ctx).Model(dao.SysMenu.Table()), option...)
|
||||
}
|
||||
|
||||
func (l *sSysMenu) List(ctx context.Context, param *model.SysMenuListParam) (data []*model.SysMenuListModel, total int, err error) {
|
||||
m := l.ModelQuery(ctx)
|
||||
if param.MenuIds != nil {
|
||||
m = m.WhereIn(dao.SysMenu.Columns().MenuId, param.MenuIds)
|
||||
}
|
||||
if param.MenuName != "" {
|
||||
m = m.WhereLike(dao.SysMenu.Columns().MenuName, "%"+param.MenuName+"%")
|
||||
}
|
||||
if param.Status != "" {
|
||||
m = m.Where(dao.SysMenu.Columns().Status, param.Status)
|
||||
}
|
||||
total, err = m.Count()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
err = m.Order(dao.SysMenu.Columns().OrderNum).Page(0, 5000).Scan(&data)
|
||||
if err == nil {
|
||||
placeDocumentCenterInMenuList(data)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 获取租户菜单列表, 系统租户返回所有菜单,其他租户返回当前租户菜单
|
||||
func (l *sSysMenu) GetTenantMenu(ctx context.Context, query *model.SysMenuListParam) (data []*model.SysMenuListModel, total int, err error) {
|
||||
// 获取当前用户信息
|
||||
tenantId := contexts.GetTenantId(ctx)
|
||||
m := l.ModelQuery(ctx)
|
||||
|
||||
if tenantId != consts.DefaultSystemTenantCode {
|
||||
// 获取租户信息
|
||||
tenantInfo, err := service.SysTenant().View(ctx, &model.SysTenantViewParam{
|
||||
TenantId: tenantId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
// 获取租户套餐
|
||||
tenantPackage, err := service.SysTenantPackage().View(ctx, &model.SysTenantPackageViewParam{
|
||||
PackageId: tenantInfo.PackageId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if tenantPackage == nil {
|
||||
g.Log().Errorf(ctx, "sSysMenu.GetTenantMenu not found tenantPackage. TenantId:%s PackageId:%d",
|
||||
tenantId, tenantInfo.PackageId)
|
||||
return nil, 0, gerror.NewCode(gcode.CodeInternalError, "系统内部错误")
|
||||
}
|
||||
if tenantPackage.MenuIds != "" {
|
||||
menuIds := strings.Split(tenantPackage.MenuIds, ",")
|
||||
m = m.WhereIn(dao.SysMenu.Columns().MenuId, menuIds)
|
||||
} else {
|
||||
return nil, 0, nil
|
||||
}
|
||||
}
|
||||
if query.MenuName != "" {
|
||||
m = m.WhereLike(dao.SysMenu.Columns().MenuName, "%"+query.MenuName+"%")
|
||||
}
|
||||
if query.Status != "" {
|
||||
m = m.Where(dao.SysMenu.Columns().Status, query.Status)
|
||||
}
|
||||
if query.MenuIds != nil {
|
||||
m = m.WhereIn(dao.SysMenu.Columns().MenuId, query.MenuIds)
|
||||
}
|
||||
|
||||
total, err = m.Count()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
err = m.Order(dao.SysMenu.Columns().OrderNum).Page(0, 5000).Scan(&data)
|
||||
if err == nil {
|
||||
placeDocumentCenterInMenuList(data)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func placeDocumentCenterInMenuList(menus []*model.SysMenuListModel) {
|
||||
order := 33
|
||||
for _, menu := range menus {
|
||||
if menu.ParentId == 0 && menu.Path == "batchExecutionLog" {
|
||||
order = menu.OrderNum + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, menu := range menus {
|
||||
if menu.MenuId == 2153 && menu.Path == "docs" && menu.MenuType == consts.SysMenuTypeDir && menu.ParentId != 0 {
|
||||
menu.ParentId = 0
|
||||
menu.OrderNum = order
|
||||
}
|
||||
}
|
||||
sort.SliceStable(menus, func(i, j int) bool { return menus[i].OrderNum < menus[j].OrderNum })
|
||||
}
|
||||
|
||||
// GetTenantMenuTree 获取租户菜单树。
|
||||
//
|
||||
// 与 GetTenantMenu 使用完全相同的租户隔离与筛选条件,区别只在于返回结构:
|
||||
// 这里由后端一次性建好嵌套 children,前端可直接交给 vxe-table 渲染,
|
||||
// 无需再依赖 treeConfig.transform 在浏览器主线程把扁平列表二次转成树。
|
||||
//
|
||||
// 建树采用「id 索引 + 单次遍历」的实现(O(n)),不使用递归逐层过滤(O(n²)),
|
||||
// 因为菜单量级已达数百行(其中绝大多数是 F 按钮),递归过滤会有可观开销。
|
||||
func (l *sSysMenu) GetTenantMenuTree(ctx context.Context, query *model.SysMenuListParam) (items []*model.SysMenuFullTreeModel, err error) {
|
||||
list, _, err := l.GetTenantMenu(ctx, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buildSysMenuFullTree(list), nil
|
||||
}
|
||||
|
||||
// buildSysMenuFullTree 把扁平菜单列表组装成嵌套树。
|
||||
//
|
||||
// 处理两种「可见根」:
|
||||
// 1. ParentId == 0 的顶层菜单;
|
||||
// 2. ParentId 指向本批次中不存在的菜单(例如按状态/名称过滤后父级被滤掉),
|
||||
// 这类节点若丢弃会导致整棵子树不可见,因此提升为根节点。
|
||||
func buildSysMenuFullTree(list []*model.SysMenuListModel) []*model.SysMenuFullTreeModel {
|
||||
if len(list) == 0 {
|
||||
return make([]*model.SysMenuFullTreeModel, 0)
|
||||
}
|
||||
|
||||
// 保持入参顺序(查询已按 order_num 排序),同时建立 id 索引。
|
||||
nodes := make([]*model.SysMenuFullTreeModel, 0, len(list))
|
||||
nodeMaps := make(map[int64]*model.SysMenuFullTreeModel, len(list))
|
||||
for _, item := range list {
|
||||
if item == nil {
|
||||
continue
|
||||
}
|
||||
node := &model.SysMenuFullTreeModel{
|
||||
SysMenuListModel: *item,
|
||||
Children: make([]*model.SysMenuFullTreeModel, 0),
|
||||
}
|
||||
nodes = append(nodes, node)
|
||||
nodeMaps[item.MenuId] = node
|
||||
}
|
||||
|
||||
roots := make([]*model.SysMenuFullTreeModel, 0)
|
||||
for _, node := range nodes {
|
||||
if node.ParentId == 0 {
|
||||
roots = append(roots, node)
|
||||
continue
|
||||
}
|
||||
if parent, ok := nodeMaps[node.ParentId]; ok {
|
||||
parent.Children = append(parent.Children, node)
|
||||
continue
|
||||
}
|
||||
// 父级不在本批次内:提升为根,避免子树整体丢失。
|
||||
roots = append(roots, node)
|
||||
}
|
||||
return roots
|
||||
}
|
||||
|
||||
// 构建树结构
|
||||
func (l *sSysMenu) MenuTree(ctx context.Context, parentMenu *model.SysMenuTree, menuList []*entity.SysMenu) (data []*model.SysMenuTree, err error) {
|
||||
data = make([]*model.SysMenuTree, 0)
|
||||
for _, menu := range menuList {
|
||||
pId := int64(0)
|
||||
if parentMenu != nil {
|
||||
pId = parentMenu.MenuId
|
||||
}
|
||||
if menu.ParentId == pId {
|
||||
item := &model.SysMenuTree{
|
||||
SysMenu: *menu,
|
||||
Children: nil,
|
||||
}
|
||||
subMenu, err := l.MenuTree(ctx, item, menuList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
item.Children = subMenu
|
||||
data = append(data, item)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户动态路由列表
|
||||
func (l *sSysMenu) GetUserMenu(ctx context.Context) (data []*entity.SysMenu, err error) {
|
||||
assignedRoleIDs, err := service.SysUser().GetUserRoleIds(ctx, contexts.GetUserId(ctx))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roleIds := make([]int64, 0)
|
||||
roleIds = append(roleIds, assignedRoleIDs...)
|
||||
g.Log().Infof(ctx, "sSysMenu.GetUserMenu roleIds: %v", roleIds)
|
||||
var validRoles []*entity.SysRole
|
||||
if len(roleIds) > 0 {
|
||||
if err := dao.SysRole.Ctx(ctx).Where("tenant_id", contexts.GetTenantId(ctx)).WhereIn("role_id", roleIds).Where("status", "0").Scan(&validRoles); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
roleIds = nil
|
||||
for _, role := range validRoles {
|
||||
roleIds = append(roleIds, role.RoleId)
|
||||
}
|
||||
if contexts.IsSuperAdmin(ctx) && contexts.GetTenantId(ctx) == consts.DefaultSystemTenantCode && slices.Contains(roleIds, consts.SuperAdminRoleId) {
|
||||
err = l.ModelQuery(ctx).Where(dao.SysMenu.Columns().Status, consts.SysMenuStatusNormal).
|
||||
Order(dao.SysMenu.Columns().OrderNum).Scan(&data)
|
||||
return
|
||||
}
|
||||
roleIds = slices.DeleteFunc(roleIds, func(roleID int64) bool {
|
||||
return roleID == consts.SuperAdminRoleId
|
||||
})
|
||||
// 获取角色菜单列表
|
||||
menuList, err := service.SysRole().GetRoleListMenu(ctx, roleIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
g.Log().Infof(ctx, "sSysMenu.GetUserMenu menuList: %v", menuList)
|
||||
menuIds := make([]int64, 0)
|
||||
for _, menu := range menuList {
|
||||
menuIds = append(menuIds, menu.MenuId)
|
||||
}
|
||||
menuIds, err = rolepolicy.RestrictMenus(ctx, contexts.GetTenantId(ctx), contexts.GetDeptId(ctx), menuIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(menuIds) == 0 {
|
||||
return []*entity.SysMenu{}, nil
|
||||
}
|
||||
g.Log().Infof(ctx, "sSysMenu.GetUserMenu menuIds: %v", menuIds)
|
||||
// 只返回角色直接勾选的菜单;未勾选的父目录不强制补齐,
|
||||
// 树构建时会把缺少授权父级的菜单提升为一级菜单。
|
||||
err = l.ModelQuery(ctx).WhereIn(dao.SysMenu.Columns().MenuId, menuIds).
|
||||
Where(dao.SysMenu.Columns().Status, consts.SysMenuStatusNormal).
|
||||
Order(dao.SysMenu.Columns().OrderNum).Scan(&data)
|
||||
g.Log().Infof(ctx, "sSysMenu.GetUserMenu data: %v", data)
|
||||
return
|
||||
}
|
||||
|
||||
// 构建用户动态路由树
|
||||
func (l *sSysMenu) BuildUserMenuTree(ctx context.Context, parentMenu *v1.RouteMenu, menuList []*entity.SysMenu, allPath string) (data v1.MenuAllRes, err error) {
|
||||
data = make(v1.MenuAllRes, 0)
|
||||
menuIdSet := make(map[int64]struct{}, len(menuList))
|
||||
for _, menu := range menuList {
|
||||
menuIdSet[menu.MenuId] = struct{}{}
|
||||
}
|
||||
for _, menu := range menuList {
|
||||
if menu.Status == consts.SysMenuStatusDisable {
|
||||
continue
|
||||
}
|
||||
if menu.MenuType == consts.SysMenuTypeBtn {
|
||||
continue
|
||||
}
|
||||
|
||||
pId := int64(0)
|
||||
if parentMenu != nil {
|
||||
pId = parentMenu.Id
|
||||
}
|
||||
isRootOrphan := parentMenu == nil && menu.ParentId != 0
|
||||
if isRootOrphan {
|
||||
_, isRootOrphan = menuIdSet[menu.ParentId]
|
||||
isRootOrphan = !isRootOrphan
|
||||
}
|
||||
if menu.ParentId == pId || isRootOrphan {
|
||||
openInNewWindow := false
|
||||
var link *string
|
||||
if menu.IsFrame == consts.SysMenuIsFrameYes {
|
||||
openInNewWindow = true
|
||||
link = &menu.Path
|
||||
}
|
||||
|
||||
query := make(map[string]string)
|
||||
if menu.QueryParam != "" {
|
||||
query2 := strings.Split(menu.QueryParam, "&")
|
||||
for _, q := range query2 {
|
||||
kv := strings.Split(q, "=")
|
||||
if len(kv) == 2 {
|
||||
query[kv[0]] = kv[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
hideInMenu := false
|
||||
if menu.Visible == consts.SysMenuVisibleHide {
|
||||
hideInMenu = true
|
||||
}
|
||||
keepAlive := true
|
||||
item := &v1.RouteMenu{
|
||||
Id: menu.MenuId,
|
||||
ParentId: menu.ParentId,
|
||||
Path: menu.Path,
|
||||
Redirect: nil,
|
||||
Name: fmt.Sprintf("menu_%d", menu.MenuId),
|
||||
Component: menu.Component,
|
||||
Meta: &v1.RouteMeta{
|
||||
Title: menu.MenuName,
|
||||
Icon: &menu.Icon,
|
||||
Order: &menu.OrderNum,
|
||||
OpenInNewWindow: &openInNewWindow,
|
||||
Query: query,
|
||||
HideInMenu: &hideInMenu,
|
||||
Authority: normalizeMenuAccessCodes(menu.Perms),
|
||||
Link: link,
|
||||
KeepAlive: &keepAlive,
|
||||
},
|
||||
}
|
||||
if hideInMenu {
|
||||
activePath := allPath + "/"
|
||||
if strings.Contains(menu.Path, "-") {
|
||||
activePath = activePath + strings.Split(menu.Path, "-")[0]
|
||||
}
|
||||
item.Meta.ActivePath = &activePath
|
||||
}
|
||||
subMenu, err := l.BuildUserMenuTree(ctx, item, menuList, allPath+"/"+menu.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
item.Children = subMenu
|
||||
if len(subMenu) == 0 && menu.MenuType == consts.SysMenuTypeDir {
|
||||
item.Children = []*v1.RouteMenu{}
|
||||
}
|
||||
data = append(data, item)
|
||||
}
|
||||
}
|
||||
// 排序
|
||||
sort.Slice(data, func(i, j int) bool {
|
||||
return *data[i].Meta.Order < *data[j].Meta.Order
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户动态路由树
|
||||
func (l *sSysMenu) GetUserMenuTree(ctx context.Context) (data v1.MenuAllRes, err error) {
|
||||
// 获取用户动态路由列表
|
||||
menuList, err := l.GetUserMenu(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
menuList = placeDocumentCenterAfterExecutionLog(menuList)
|
||||
// 构建树结构
|
||||
data, err = l.BuildUserMenuTree(ctx, nil, menuList, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func placeDocumentCenterAfterExecutionLog(menuList []*entity.SysMenu) []*entity.SysMenu {
|
||||
menus := append([]*entity.SysMenu(nil), menuList...)
|
||||
order := 33
|
||||
for _, menu := range menus {
|
||||
if menu.ParentId == 0 && menu.Path == "batchExecutionLog" {
|
||||
order = menu.OrderNum + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
for index, menu := range menus {
|
||||
if menu.Path != "docs" || menu.MenuName != "文档中心" || menu.MenuType != consts.SysMenuTypeDir || menu.ParentId == 0 {
|
||||
continue
|
||||
}
|
||||
copyOfMenu := *menu
|
||||
copyOfMenu.ParentId = 0
|
||||
copyOfMenu.Level = 1
|
||||
copyOfMenu.OrderNum = order
|
||||
menus[index] = ©OfMenu
|
||||
}
|
||||
return menus
|
||||
}
|
||||
|
||||
func normalizeMenuAccessCodes(perms string) []string {
|
||||
items := strings.Split(perms, ",")
|
||||
codes := make([]string, 0, len(items))
|
||||
seen := make(map[string]struct{}, len(items))
|
||||
for _, item := range items {
|
||||
item = strings.TrimSpace(item)
|
||||
if item == "" {
|
||||
continue
|
||||
}
|
||||
if !strings.HasPrefix(item, consts.SysCheckPermissionPrefix) {
|
||||
item = consts.SysCheckPermissionMenuPrefix + item
|
||||
}
|
||||
if _, ok := seen[item]; ok {
|
||||
continue
|
||||
}
|
||||
seen[item] = struct{}{}
|
||||
codes = append(codes, item)
|
||||
}
|
||||
return codes
|
||||
}
|
||||
|
||||
func (l *sSysMenu) GetSysMenuView(ctx context.Context, menuId int64) (data *model.SysMenuViewModel, err error) {
|
||||
menu := &entity.SysMenu{}
|
||||
err = l.ModelQuery(ctx).Where(dao.SysMenu.Columns().MenuId, menuId).Scan(menu)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data = &model.SysMenuViewModel{
|
||||
SysMenu: *menu,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (l *sSysMenu) UpdateSysMenu(ctx context.Context, menu *model.SysMenuUpdateModel) (data *model.SysMenuViewModel, err error) {
|
||||
menu.UpdatedAt = gtime.Now()
|
||||
menu.UpdatedBy = contexts.GetUserId(ctx)
|
||||
_, err = l.Model(ctx).Where(dao.SysMenu.Columns().MenuId, menu.MenuId).Data(menu).OmitNil().Update(menu)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
event.EventsInstance().Emit(ctx, consts.EventKeyDBSysMenuUpdate, menu.MenuId)
|
||||
data, err = l.GetSysMenuView(ctx, menu.MenuId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (l *sSysMenu) AddSysMenu(ctx context.Context, menu *model.SysMenuAddModel) (data *model.SysMenuViewModel, err error) {
|
||||
menu.CreatedDept = contexts.GetDeptId(ctx)
|
||||
menu.CreatedAt = gtime.Now()
|
||||
menu.CreatedBy = contexts.GetUserId(ctx)
|
||||
menu.UpdatedAt = gtime.Now()
|
||||
menu.UpdatedBy = contexts.GetUserId(ctx)
|
||||
re, err := l.Model(ctx).Data(menu).Insert()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
menuId, err := re.LastInsertId()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
event.EventsInstance().Emit(ctx, consts.EventKeyDBSysMenuCreate, menuId)
|
||||
data, err = l.GetSysMenuView(ctx, menuId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (l *sSysMenu) DeleteSysMenu(ctx context.Context, menuId int64) (err error) {
|
||||
_, err = l.Model(ctx).Where(dao.SysMenu.Columns().MenuId, menuId).Delete()
|
||||
event.EventsInstance().Emit(ctx, consts.EventKeyDBSysMenuDelete, menuId)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sSysMenu) GetFastList(ctx context.Context) (res map[int64]*entity.SysMenu, err error) {
|
||||
var models []*entity.SysMenu
|
||||
if err = s.ModelQuery(ctx).Scan(&models); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
res = make(map[int64]*entity.SysMenu, len(models))
|
||||
for _, v := range models {
|
||||
res[v.MenuId] = v
|
||||
}
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user