add logic and menu service

This commit is contained in:
Yavolte 2025-06-18 14:46:21 +08:00
parent ef4ad92e35
commit 79a9746447
20 changed files with 2860 additions and 348 deletions

80
formatter.go 100644
View File

@ -0,0 +1,80 @@
package aeusadmin
import (
"context"
"fmt"
"git.nobla.cn/golang/aeus-admin/internal/logic"
"git.nobla.cn/golang/rest"
"git.nobla.cn/golang/rest/types"
"gorm.io/gorm"
)
type Formatter struct {
db *gorm.DB
user *logic.User
department *logic.Department
role *logic.Role
menu *logic.Menu
}
func (f *Formatter) FormatUser(ctx context.Context, value, model any, scm *types.Schema) any {
if values, err := f.user.GetLabels(ctx); err == nil {
for _, row := range values {
if row.Value == value {
return fmt.Sprintf("%s(%s)", row.Label, row.Value)
}
}
}
return value
}
func (f *Formatter) FormatDepartment(ctx context.Context, value, model any, scm *types.Schema) any {
if values, err := f.department.GetLabels(ctx); err == nil {
for _, row := range values {
if row.Value == value {
return row.Label
}
}
}
return value
}
func (f *Formatter) FormatRole(ctx context.Context, value, model any, scm *types.Schema) any {
if values, err := f.role.GetLabels(ctx); err == nil {
for _, row := range values {
if row.Value == value {
return row.Label
}
}
}
return value
}
func (f *Formatter) FormatMenu(ctx context.Context, value, model any, scm *types.Schema) any {
if values, err := f.menu.GetLabels(ctx); err == nil {
for _, row := range values {
if row.Value == value {
return row.Label
}
}
}
return value
}
func (f *Formatter) Register() {
rest.DefaultFormatter.Register("user", f.FormatUser)
rest.DefaultFormatter.Register("department", f.FormatDepartment)
rest.DefaultFormatter.Register("role", f.FormatRole)
rest.DefaultFormatter.Register("menu", f.FormatMenu)
}
func NewFormatter(db *gorm.DB) *Formatter {
return &Formatter{
db: db,
user: logic.NewUserLogic(db),
department: logic.NewDepartmentLogic(db),
role: logic.NewRoleLogic(db),
menu: logic.NewMenuLogic(db),
}
}

View File

@ -0,0 +1,93 @@
package logic
import (
"context"
"fmt"
"strings"
"git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
"git.nobla.cn/golang/rest"
"git.nobla.cn/golang/rest/types"
"gorm.io/gorm"
)
type Department struct {
db *gorm.DB
sqlDependency *dbcache.SqlDependency
}
func (u *Department) RecursiveDepartment(ctx context.Context, parent int64, level int, departments []*models.Department) []*types.TypeValue[int64] {
var (
child []*types.TypeValue[int64]
)
values := make([]*types.TypeValue[int64], 0, len(departments))
for _, dept := range departments {
if dept.ParentId == parent {
if level == 0 {
values = append(values, &types.TypeValue[int64]{
Label: dept.Name,
Value: dept.Id,
})
} else {
values = append(values, &types.TypeValue[int64]{
Label: strings.Repeat("--", level) + dept.Name,
Value: dept.Id,
})
}
child = u.RecursiveDepartment(ctx, dept.Id, level+1, departments)
if len(child) > 0 {
for _, row := range child {
values = append(values, row)
}
}
}
}
return values
}
// GetLevelLabels 获取层级标签
func (u *Department) GetLevelLabels(ctx context.Context) (values []*types.TypeValue[int64], err error) {
values, err = dbcache.TryCache(ctx, fmt.Sprintf("department:level:labels"), func(tx *gorm.DB) ([]*types.TypeValue[int64], error) {
var values []*models.Department
if err = tx.Find(&values).Error; err != nil {
return nil, err
}
return u.RecursiveDepartment(ctx, 0, 0, values), nil
},
dbcache.WithDB(u.db),
dbcache.WithDependency(u.sqlDependency),
)
return
}
// GetLabels 获取用户标签
func (u *Department) GetLabels(ctx context.Context) (values []*types.TypeValue[int64], err error) {
values, err = dbcache.TryCache(ctx, fmt.Sprintf("department:labels"), func(tx *gorm.DB) ([]*types.TypeValue[int64], error) {
return rest.ModelTypes[int64](ctx, tx, &models.Department{}, "", "name", "id")
},
dbcache.WithDB(u.db),
dbcache.WithDependency(u.sqlDependency),
)
return
}
// GetDepartments 获取部门列表
func (u *Department) GetDepartments(ctx context.Context) (values []*models.Department, err error) {
values, err = dbcache.TryCache(ctx, fmt.Sprintf("department:list"), func(tx *gorm.DB) ([]*models.Department, error) {
var items []*models.Department
err = tx.Find(&items).Error
return items, err
},
dbcache.WithDB(u.db),
dbcache.WithDependency(u.sqlDependency),
)
return
}
func NewDepartmentLogic(db *gorm.DB) *Department {
return &Department{
db: db,
sqlDependency: dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM departments"),
}
}

View File

@ -0,0 +1,44 @@
package logic
import (
"context"
"fmt"
"git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
"git.nobla.cn/golang/rest"
"git.nobla.cn/golang/rest/types"
"gorm.io/gorm"
)
type Menu struct {
db *gorm.DB
sqlDependency *dbcache.SqlDependency
}
func (u *Menu) GetMenus(ctx context.Context) (values []*models.Menu, err error) {
return dbcache.TryCache(ctx, "menus", func(tx *gorm.DB) ([]*models.Menu, error) {
var items []*models.Menu
err = tx.Order("`position`,`id` ASC").Find(&items).Error
return items, err
},
dbcache.WithDB(u.db),
dbcache.WithDependency(u.sqlDependency),
)
}
func (u *Menu) GetLabels(ctx context.Context) (values []*types.TypeValue[string], err error) {
return dbcache.TryCache(ctx, fmt.Sprintf("menu:labels"), func(tx *gorm.DB) ([]*types.TypeValue[string], error) {
return rest.ModelTypes[string](ctx, tx, &models.Menu{}, "", "label", "name")
},
dbcache.WithDB(u.db),
dbcache.WithDependency(u.sqlDependency),
)
}
func NewMenuLogic(db *gorm.DB) *Menu {
return &Menu{
db: db,
sqlDependency: dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM menus"),
}
}

View File

@ -0,0 +1,54 @@
package logic
import (
"context"
"fmt"
"git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
"git.nobla.cn/golang/rest"
"git.nobla.cn/golang/rest/types"
"gorm.io/gorm"
)
type Role struct {
db *gorm.DB
sqlDependency *dbcache.SqlDependency
permissionSqlDependency *dbcache.SqlDependency
}
func (u *Role) GetLabels(ctx context.Context) (values []*types.TypeValue[string], err error) {
values, err = dbcache.TryCache(ctx, fmt.Sprintf("role:labels"), func(tx *gorm.DB) ([]*types.TypeValue[string], error) {
return rest.ModelTypes[string](ctx, tx, &models.Role{}, "", "label", "name")
},
dbcache.WithDB(u.db),
dbcache.WithDependency(u.sqlDependency),
)
return
}
func (u *Role) GetPermissions(ctx context.Context, role string) (values []*models.Permission, err error) {
values, err = dbcache.TryCache(ctx, fmt.Sprintf("role:permissions-items:%s", role), func(tx *gorm.DB) ([]*models.Permission, error) {
var items []*models.Permission
if role == "" {
err = tx.Find(&items).Error
} else {
err = tx.
Where("`permission` IN (SELECT `permission` FROM role_permissions WHERE `role` = ?)", role).
Find(&items).Error
}
return items, err
},
dbcache.WithDB(u.db),
dbcache.WithDependency(u.permissionSqlDependency),
)
return
}
func NewRoleLogic(db *gorm.DB) *Role {
return &Role{
db: db,
sqlDependency: dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM roles"),
permissionSqlDependency: dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM permissions"),
}
}

View File

@ -0,0 +1,63 @@
package logic
import (
"context"
"fmt"
"time"
"git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
"git.nobla.cn/golang/rest"
"git.nobla.cn/golang/rest/types"
"gorm.io/gorm"
)
type User struct {
db *gorm.DB
sqlDependency *dbcache.SqlDependency
}
// GetPermissions 获取用户权限
func (u *User) GetPermissions(ctx context.Context, uid string) (permissions []string, err error) {
permissions, err = dbcache.TryCache(ctx, fmt.Sprintf("user:permissions:%s", uid), func(tx *gorm.DB) ([]string, error) {
var ss []string
err = tx.Select("permission").Model(&models.RolePermission{}).
Joins("LEFT JOIN users on users.role = role_permissions.role").
Where("users.uid = ?", uid).
Pluck("permission", &ss).
Error
return ss, err
}, dbcache.WithCacheDuration(time.Minute), dbcache.WithDB(u.db))
return
}
// GetLabels 获取用户标签
func (u *User) GetLabels(ctx context.Context) (values []*types.TypeValue[string], err error) {
values, err = dbcache.TryCache(ctx, fmt.Sprintf("user:labels"), func(tx *gorm.DB) ([]*types.TypeValue[string], error) {
return rest.ModelTypes[string](ctx, tx, &models.User{}, "", "username", "uid")
},
dbcache.WithDB(u.db),
dbcache.WithDependency(u.sqlDependency),
)
return
}
// GeUsers 获取部门列表
func (u *User) GeUsers(ctx context.Context) (values []*models.User, err error) {
values, err = dbcache.TryCache(ctx, fmt.Sprintf("user:list"), func(tx *gorm.DB) ([]*models.User, error) {
var items []*models.User
err = tx.Find(&items).Error
return items, err
},
dbcache.WithDB(u.db),
dbcache.WithDependency(u.sqlDependency),
)
return
}
func NewUserLogic(db *gorm.DB) *User {
return &User{
db: db,
sqlDependency: dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM users"),
}
}

View File

@ -1,10 +1,7 @@
package defaults package migrate
import ( import (
"errors"
"git.nobla.cn/golang/aeus-admin/models" "git.nobla.cn/golang/aeus-admin/models"
"gorm.io/gorm"
) )
var ( var (
@ -84,46 +81,3 @@ func init() {
systemDepartment.Description = "" systemDepartment.Description = ""
defaultDepartments = append(defaultDepartments, systemDepartment) defaultDepartments = append(defaultDepartments, systemDepartment)
} }
func MergeMenu(db *gorm.DB, model *models.Menu) (err error) {
if err = db.Where("name = ?", model.Name).First(model).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
err = db.Create(model).Error
}
}
return
}
func Generate(db *gorm.DB) (err error) {
var (
n int64
)
for _, row := range defaultMenus {
if err = MergeMenu(db, row); err != nil {
return
}
}
if db.Model(&models.Role{}).Count(&n); n == 0 {
db.Create(defaultRoles)
permissions := make([]*models.Permission, 0)
db.Find(&permissions)
for _, row := range defaultRoles {
items := make([]*models.RolePermission, 0)
for _, perm := range permissions {
item := &models.RolePermission{}
item.Role = row.Name
item.Permission = perm.Permission
items = append(items, item)
}
db.Save(items)
}
}
if db.Model(&models.Department{}).Count(&n); n == 0 {
db.Create(defaultDepartments)
}
if db.Model(&models.User{}).Count(&n); n == 0 {
db.Create(defaultUsers)
}
return
}

67
migrate/migrate.go 100644
View File

@ -0,0 +1,67 @@
package migrate
import (
"errors"
"git.nobla.cn/golang/aeus-admin/models"
"gorm.io/gorm"
)
// Menu 合并菜单
func Menu(db *gorm.DB, model *models.Menu) (err error) {
if err = db.Where("name = ?", model.Name).First(model).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
err = db.Create(model).Error
}
}
return
}
// Permission 合并权限数据
func Permission(db *gorm.DB, menuName string, permission string, label string) (permissionModel *models.Permission, err error) {
permissionModel = &models.Permission{}
if err = db.Where("permission = ? AND menu = ?", permission, menuName).First(permissionModel).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
permissionModel.Menu = menuName
permissionModel.Label = label
permissionModel.Permission = permission
err = db.Create(permissionModel).Error
}
}
return
}
// Default 合并初始化数据集
func Default(db *gorm.DB) (err error) {
var (
n int64
)
for _, row := range defaultMenus {
if err = Menu(db, row); err != nil {
return
}
}
if db.Model(&models.Role{}).Count(&n); n == 0 {
db.Create(defaultRoles)
permissions := make([]*models.Permission, 0)
db.Find(&permissions)
for _, row := range defaultRoles {
items := make([]*models.RolePermission, 0)
for _, perm := range permissions {
item := &models.RolePermission{}
item.Role = row.Name
item.Permission = perm.Permission
items = append(items, item)
}
db.Save(items)
}
}
if db.Model(&models.Department{}).Count(&n); n == 0 {
db.Create(defaultDepartments)
}
if db.Model(&models.User{}).Count(&n); n == 0 {
db.Create(defaultUsers)
}
return
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@ message Menu {
int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment:"菜单ID"}]; int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment:"菜单ID"}];
int64 created_at = 2 [(aeus.field)={scenarios:"view;export",comment:"创建时间"}]; int64 created_at = 2 [(aeus.field)={scenarios:"view;export",comment:"创建时间"}];
int64 updated_at = 3 [(aeus.field)={gorm:"index",scenarios:"view;export",comment:"更新时间"}]; int64 updated_at = 3 [(aeus.field)={gorm:"index",scenarios:"view;export",comment:"更新时间"}];
string parent = 4 [(aeus.field)={gorm:"index;size:60",props:"readonly:update",comment:"父级菜单"}]; string parent = 4 [(aeus.field)={gorm:"index;size:60",props:"readonly:update",live:"type:dropdown;url:/menu/level-labels",format:"menu",comment:"父级菜单"}];
string name = 5 [(aeus.field)={gorm:"index;size:60",props:"readonly:update",rule:"unique;required",comment: "组件名称"},(validate.rules).string = {max_len: 60}]; string name = 5 [(aeus.field)={gorm:"index;size:60",props:"readonly:update",rule:"unique;required",comment: "组件名称"},(validate.rules).string = {max_len: 60}];
string label = 6 [(aeus.field)={gorm:"size:120",rule:"required",comment: "菜单标题"},(validate.rules).string = {max_len: 120}]; string label = 6 [(aeus.field)={gorm:"size:120",rule:"required",comment: "菜单标题"},(validate.rules).string = {max_len: 120}];
string uri = 7 [(aeus.field)={gorm:"size:512",rule:"required",scenarios:"create;update;view;export",comment: "菜单链接"},(validate.rules).string = {max_len: 512}]; string uri = 7 [(aeus.field)={gorm:"size:512",rule:"required",scenarios:"create;update;view;export",comment: "菜单链接"},(validate.rules).string = {max_len: 512}];
@ -26,6 +26,7 @@ message Menu {
bool hidden = 10 [(aeus.field)={scenarios:"create;update;view;export",comment:"是否隐藏"}]; bool hidden = 10 [(aeus.field)={scenarios:"create;update;view;export",comment:"是否隐藏"}];
bool public = 11 [(aeus.field)={scenarios:"create;update;view;export",comment:"是否公开"}]; bool public = 11 [(aeus.field)={scenarios:"create;update;view;export",comment:"是否公开"}];
string description = 12 [(aeus.field)={gorm:"size:1024",scenarios:"create;update;view;export;list",format:"textarea",comment: "备注说明"},(validate.rules).string = {max_len: 1024}]; string description = 12 [(aeus.field)={gorm:"size:1024",scenarios:"create;update;view;export;list",format:"textarea",comment: "备注说明"},(validate.rules).string = {max_len: 1024}];
int64 position = 13 [(aeus.field)={comment:"排序",scenarios:"create;update"}];
} }
// Role // Role
@ -47,9 +48,11 @@ message Permission {
table: "permissions" table: "permissions"
}; };
int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment: "权限ID"}]; int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment: "权限ID"}];
string menu = 2 [(aeus.field)={gorm:"index;size:60",rule:"required",comment: "所属菜单"}]; int64 created_at = 2 [(aeus.field)={scenarios:"view;export",comment:"创建时间"}];
string permission = 3 [(aeus.field)={gorm:"index;size:60",rule:"required",comment: "权限名称"},(validate.rules).string = {max_len: 60}]; int64 updated_at = 3 [(aeus.field)={gorm:"index",scenarios:"view;export",comment:"更新时间"}];
string label = 4 [(aeus.field)={gorm:"size:60",rule:"required",comment: "权限标题"},(validate.rules).string = {max_len: 60}]; string menu = 4 [(aeus.field)={gorm:"index;size:60",format:"menu",rule:"required",comment: "所属菜单"}];
string permission = 5 [(aeus.field)={gorm:"index;size:60",rule:"required",comment: "权限名称"},(validate.rules).string = {max_len: 60}];
string label = 6 [(aeus.field)={gorm:"size:60",rule:"required",comment: "权限标题"},(validate.rules).string = {max_len: 60}];
} }
// RolePermission // RolePermission
@ -92,7 +95,7 @@ message Department {
int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment:"ID"}]; int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment:"ID"}];
int64 created_at = 2 [(aeus.field)={scenarios:"view;export",comment:"创建时间"}]; int64 created_at = 2 [(aeus.field)={scenarios:"view;export",comment:"创建时间"}];
int64 updated_at = 3 [(aeus.field)={gorm:"index",scenarios:"view;export",comment:"更新时间"}]; int64 updated_at = 3 [(aeus.field)={gorm:"index",scenarios:"view;export",comment:"更新时间"}];
int64 parent_id = 4 [(aeus.field)={format:"department",comment:"父级部门"}]; int64 parent_id = 4 [(aeus.field)={live:"type:dropdown;url:/department/level-labels",format:"department",comment:"父级部门"}];
string name = 5 [(aeus.field)={gorm:"size:20",rule:"required",comment: "部门名称"},(validate.rules).string = {max_len: 20}]; string name = 5 [(aeus.field)={gorm:"size:20",rule:"required",comment: "部门名称"},(validate.rules).string = {max_len: 20}];
string description = 6 [(aeus.field)={gorm:"size:1024",scenarios:"create;update;view;export;list",format:"textarea",comment: "备注说明"},(validate.rules).string = {max_len: 1024}]; string description = 6 [(aeus.field)={gorm:"size:1024",scenarios:"create;update;view;export;list",format:"textarea",comment: "备注说明"},(validate.rules).string = {max_len: 1024}];
} }
@ -289,6 +292,13 @@ message DepartmentLabelValue {
int64 value = 2; int64 value = 2;
} }
message DepartmentUserValue {
string label = 1;
string value = 2;
bool isuser = 3;
repeated DepartmentUserValue children = 4;
}
message GetDepartmentLabelRequest { message GetDepartmentLabelRequest {
} }
@ -296,6 +306,26 @@ message GetDepartmentLabelResponse {
repeated DepartmentLabelValue data = 1; repeated DepartmentLabelValue data = 1;
} }
message GetDepartmentUserRequest {
}
message GetDepartmentUserResponse {
repeated DepartmentUserValue data = 1;
}
message DepartmentLevelValue {
string label = 1;
int64 value = 2;
repeated DepartmentLevelValue children = 4;
}
message GetDepartmentLevelLabelsRequest {
}
message GetDepartmentLevelLabelsResponse {
repeated DepartmentLevelValue data = 1;
}
service DepartmentService { service DepartmentService {
// //
rpc GetDepartmentLabels(GetDepartmentLabelRequest) returns (GetDepartmentLabelResponse) { rpc GetDepartmentLabels(GetDepartmentLabelRequest) returns (GetDepartmentLabelResponse) {
@ -303,6 +333,16 @@ service DepartmentService {
get: "/department/labels" get: "/department/labels"
}; };
} }
rpc GetDepartmentUsers(GetDepartmentUserRequest) returns (GetDepartmentUserResponse) {
option (google.api.http) = {
get: "/department/users"
};
}
rpc GetDepartmentLevelLabels(GetDepartmentLevelLabelsRequest) returns (GetDepartmentLevelLabelsResponse) {
option (google.api.http) = {
get: "/department/level-labels"
};
}
} }
message GetRoleLabelRequest { message GetRoleLabelRequest {
@ -352,6 +392,27 @@ service RoleService {
} }
} }
message MenuLevelValue {
string label = 1;
string value = 2;
repeated MenuLevelValue children = 4;
}
message GetMenuLevelLabelsRequest {
}
message GetMenuLevelLabelsResponse {
repeated MenuLevelValue data = 1;
}
service MenuService {
rpc GetMenuLevelLabels(GetMenuLevelLabelsRequest) returns (GetMenuLevelLabelsResponse) {
option (google.api.http) = {
get: "/menu/level-labels"
};
}
}
message LoginRequest { message LoginRequest {
string username = 1; string username = 1;

View File

@ -368,6 +368,8 @@ var UserService_ServiceDesc = grpc.ServiceDesc{
const ( const (
DepartmentService_GetDepartmentLabels_FullMethodName = "/organize.DepartmentService/GetDepartmentLabels" DepartmentService_GetDepartmentLabels_FullMethodName = "/organize.DepartmentService/GetDepartmentLabels"
DepartmentService_GetDepartmentUsers_FullMethodName = "/organize.DepartmentService/GetDepartmentUsers"
DepartmentService_GetDepartmentLevelLabels_FullMethodName = "/organize.DepartmentService/GetDepartmentLevelLabels"
) )
// DepartmentServiceClient is the client API for DepartmentService service. // DepartmentServiceClient is the client API for DepartmentService service.
@ -376,6 +378,8 @@ const (
type DepartmentServiceClient interface { type DepartmentServiceClient interface {
// 获取部门标签 // 获取部门标签
GetDepartmentLabels(ctx context.Context, in *GetDepartmentLabelRequest, opts ...grpc.CallOption) (*GetDepartmentLabelResponse, error) GetDepartmentLabels(ctx context.Context, in *GetDepartmentLabelRequest, opts ...grpc.CallOption) (*GetDepartmentLabelResponse, error)
GetDepartmentUsers(ctx context.Context, in *GetDepartmentUserRequest, opts ...grpc.CallOption) (*GetDepartmentUserResponse, error)
GetDepartmentLevelLabels(ctx context.Context, in *GetDepartmentLevelLabelsRequest, opts ...grpc.CallOption) (*GetDepartmentLevelLabelsResponse, error)
} }
type departmentServiceClient struct { type departmentServiceClient struct {
@ -396,12 +400,34 @@ func (c *departmentServiceClient) GetDepartmentLabels(ctx context.Context, in *G
return out, nil return out, nil
} }
func (c *departmentServiceClient) GetDepartmentUsers(ctx context.Context, in *GetDepartmentUserRequest, opts ...grpc.CallOption) (*GetDepartmentUserResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetDepartmentUserResponse)
err := c.cc.Invoke(ctx, DepartmentService_GetDepartmentUsers_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *departmentServiceClient) GetDepartmentLevelLabels(ctx context.Context, in *GetDepartmentLevelLabelsRequest, opts ...grpc.CallOption) (*GetDepartmentLevelLabelsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetDepartmentLevelLabelsResponse)
err := c.cc.Invoke(ctx, DepartmentService_GetDepartmentLevelLabels_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// DepartmentServiceServer is the server API for DepartmentService service. // DepartmentServiceServer is the server API for DepartmentService service.
// All implementations must embed UnimplementedDepartmentServiceServer // All implementations must embed UnimplementedDepartmentServiceServer
// for forward compatibility. // for forward compatibility.
type DepartmentServiceServer interface { type DepartmentServiceServer interface {
// 获取部门标签 // 获取部门标签
GetDepartmentLabels(context.Context, *GetDepartmentLabelRequest) (*GetDepartmentLabelResponse, error) GetDepartmentLabels(context.Context, *GetDepartmentLabelRequest) (*GetDepartmentLabelResponse, error)
GetDepartmentUsers(context.Context, *GetDepartmentUserRequest) (*GetDepartmentUserResponse, error)
GetDepartmentLevelLabels(context.Context, *GetDepartmentLevelLabelsRequest) (*GetDepartmentLevelLabelsResponse, error)
mustEmbedUnimplementedDepartmentServiceServer() mustEmbedUnimplementedDepartmentServiceServer()
} }
@ -415,6 +441,12 @@ type UnimplementedDepartmentServiceServer struct{}
func (UnimplementedDepartmentServiceServer) GetDepartmentLabels(context.Context, *GetDepartmentLabelRequest) (*GetDepartmentLabelResponse, error) { func (UnimplementedDepartmentServiceServer) GetDepartmentLabels(context.Context, *GetDepartmentLabelRequest) (*GetDepartmentLabelResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetDepartmentLabels not implemented") return nil, status.Errorf(codes.Unimplemented, "method GetDepartmentLabels not implemented")
} }
func (UnimplementedDepartmentServiceServer) GetDepartmentUsers(context.Context, *GetDepartmentUserRequest) (*GetDepartmentUserResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetDepartmentUsers not implemented")
}
func (UnimplementedDepartmentServiceServer) GetDepartmentLevelLabels(context.Context, *GetDepartmentLevelLabelsRequest) (*GetDepartmentLevelLabelsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetDepartmentLevelLabels not implemented")
}
func (UnimplementedDepartmentServiceServer) mustEmbedUnimplementedDepartmentServiceServer() {} func (UnimplementedDepartmentServiceServer) mustEmbedUnimplementedDepartmentServiceServer() {}
func (UnimplementedDepartmentServiceServer) testEmbeddedByValue() {} func (UnimplementedDepartmentServiceServer) testEmbeddedByValue() {}
@ -454,6 +486,42 @@ func _DepartmentService_GetDepartmentLabels_Handler(srv interface{}, ctx context
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _DepartmentService_GetDepartmentUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetDepartmentUserRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DepartmentServiceServer).GetDepartmentUsers(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: DepartmentService_GetDepartmentUsers_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DepartmentServiceServer).GetDepartmentUsers(ctx, req.(*GetDepartmentUserRequest))
}
return interceptor(ctx, in, info, handler)
}
func _DepartmentService_GetDepartmentLevelLabels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetDepartmentLevelLabelsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DepartmentServiceServer).GetDepartmentLevelLabels(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: DepartmentService_GetDepartmentLevelLabels_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DepartmentServiceServer).GetDepartmentLevelLabels(ctx, req.(*GetDepartmentLevelLabelsRequest))
}
return interceptor(ctx, in, info, handler)
}
// DepartmentService_ServiceDesc is the grpc.ServiceDesc for DepartmentService service. // DepartmentService_ServiceDesc is the grpc.ServiceDesc for DepartmentService service.
// It's only intended for direct use with grpc.RegisterService, // It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy) // and not to be introspected or modified (even as a copy)
@ -465,6 +533,14 @@ var DepartmentService_ServiceDesc = grpc.ServiceDesc{
MethodName: "GetDepartmentLabels", MethodName: "GetDepartmentLabels",
Handler: _DepartmentService_GetDepartmentLabels_Handler, Handler: _DepartmentService_GetDepartmentLabels_Handler,
}, },
{
MethodName: "GetDepartmentUsers",
Handler: _DepartmentService_GetDepartmentUsers_Handler,
},
{
MethodName: "GetDepartmentLevelLabels",
Handler: _DepartmentService_GetDepartmentLevelLabels_Handler,
},
}, },
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
Metadata: "organize.proto", Metadata: "organize.proto",
@ -652,6 +728,108 @@ var RoleService_ServiceDesc = grpc.ServiceDesc{
Metadata: "organize.proto", Metadata: "organize.proto",
} }
const (
MenuService_GetMenuLevelLabels_FullMethodName = "/organize.MenuService/GetMenuLevelLabels"
)
// MenuServiceClient is the client API for MenuService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type MenuServiceClient interface {
GetMenuLevelLabels(ctx context.Context, in *GetMenuLevelLabelsRequest, opts ...grpc.CallOption) (*GetMenuLevelLabelsResponse, error)
}
type menuServiceClient struct {
cc grpc.ClientConnInterface
}
func NewMenuServiceClient(cc grpc.ClientConnInterface) MenuServiceClient {
return &menuServiceClient{cc}
}
func (c *menuServiceClient) GetMenuLevelLabels(ctx context.Context, in *GetMenuLevelLabelsRequest, opts ...grpc.CallOption) (*GetMenuLevelLabelsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetMenuLevelLabelsResponse)
err := c.cc.Invoke(ctx, MenuService_GetMenuLevelLabels_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// MenuServiceServer is the server API for MenuService service.
// All implementations must embed UnimplementedMenuServiceServer
// for forward compatibility.
type MenuServiceServer interface {
GetMenuLevelLabels(context.Context, *GetMenuLevelLabelsRequest) (*GetMenuLevelLabelsResponse, error)
mustEmbedUnimplementedMenuServiceServer()
}
// UnimplementedMenuServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedMenuServiceServer struct{}
func (UnimplementedMenuServiceServer) GetMenuLevelLabels(context.Context, *GetMenuLevelLabelsRequest) (*GetMenuLevelLabelsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetMenuLevelLabels not implemented")
}
func (UnimplementedMenuServiceServer) mustEmbedUnimplementedMenuServiceServer() {}
func (UnimplementedMenuServiceServer) testEmbeddedByValue() {}
// UnsafeMenuServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to MenuServiceServer will
// result in compilation errors.
type UnsafeMenuServiceServer interface {
mustEmbedUnimplementedMenuServiceServer()
}
func RegisterMenuServiceServer(s grpc.ServiceRegistrar, srv MenuServiceServer) {
// If the following call pancis, it indicates UnimplementedMenuServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&MenuService_ServiceDesc, srv)
}
func _MenuService_GetMenuLevelLabels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetMenuLevelLabelsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MenuServiceServer).GetMenuLevelLabels(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: MenuService_GetMenuLevelLabels_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MenuServiceServer).GetMenuLevelLabels(ctx, req.(*GetMenuLevelLabelsRequest))
}
return interceptor(ctx, in, info, handler)
}
// MenuService_ServiceDesc is the grpc.ServiceDesc for MenuService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var MenuService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "organize.MenuService",
HandlerType: (*MenuServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetMenuLevelLabels",
Handler: _MenuService_GetMenuLevelLabels_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "organize.proto",
}
const ( const (
AuthService_Login_FullMethodName = "/organize.AuthService/Login" AuthService_Login_FullMethodName = "/organize.AuthService/Login"
AuthService_Logout_FullMethodName = "/organize.AuthService/Logout" AuthService_Logout_FullMethodName = "/organize.AuthService/Logout"

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-aeus. DO NOT EDIT. // Code generated by protoc-gen-go-aeus. DO NOT EDIT.
// source: organize.proto // source: organize.proto
// date: 2025-06-17 18:12:28 // date: 2025-06-18 14:37:24
package pb package pb
@ -28,6 +28,10 @@ type UserServiceHttpServer interface {
type DepartmentServiceHttpServer interface { type DepartmentServiceHttpServer interface {
GetDepartmentLabels(context.Context, *GetDepartmentLabelRequest) (*GetDepartmentLabelResponse, error) GetDepartmentLabels(context.Context, *GetDepartmentLabelRequest) (*GetDepartmentLabelResponse, error)
GetDepartmentUsers(context.Context, *GetDepartmentUserRequest) (*GetDepartmentUserResponse, error)
GetDepartmentLevelLabels(context.Context, *GetDepartmentLevelLabelsRequest) (*GetDepartmentLevelLabelsResponse, error)
} }
type RoleServiceHttpServer interface { type RoleServiceHttpServer interface {
@ -38,6 +42,10 @@ type RoleServiceHttpServer interface {
SaveRolePermission(context.Context, *SaveRolePermissionRequest) (*SaveRolePermissionResponse, error) SaveRolePermission(context.Context, *SaveRolePermissionRequest) (*SaveRolePermissionResponse, error)
} }
type MenuServiceHttpServer interface {
GetMenuLevelLabels(context.Context, *GetMenuLevelLabelsRequest) (*GetMenuLevelLabelsResponse, error)
}
type AuthServiceHttpServer interface { type AuthServiceHttpServer interface {
Login(context.Context, *LoginRequest) (*LoginResponse, error) Login(context.Context, *LoginRequest) (*LoginResponse, error)
@ -212,6 +220,38 @@ func handleDepartmentServiceGetDepartmentLabels(s DepartmentServiceHttpServer) h
} }
} }
func handleDepartmentServiceGetDepartmentUsers(s DepartmentServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &GetDepartmentUserRequest{}
if res, err := s.GetDepartmentUsers(ctx.Context(), req); err != nil {
if er, ok := err.(*errors.Error); ok {
return ctx.Error(er.Code, er.Message)
} else {
return ctx.Error(errors.Unavailable, err.Error())
}
} else {
return ctx.Success(res)
}
}
}
func handleDepartmentServiceGetDepartmentLevelLabels(s DepartmentServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &GetDepartmentLevelLabelsRequest{}
if res, err := s.GetDepartmentLevelLabels(ctx.Context(), req); err != nil {
if er, ok := err.(*errors.Error); ok {
return ctx.Error(er.Code, er.Message)
} else {
return ctx.Error(errors.Unavailable, err.Error())
}
} else {
return ctx.Success(res)
}
}
}
// 获取角色标签 // 获取角色标签
func handleRoleServiceGetRoleLabels(s RoleServiceHttpServer) http.HandleFunc { func handleRoleServiceGetRoleLabels(s RoleServiceHttpServer) http.HandleFunc {
@ -272,6 +312,22 @@ func handleRoleServiceSaveRolePermission(s RoleServiceHttpServer) http.HandleFun
} }
} }
func handleMenuServiceGetMenuLevelLabels(s MenuServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &GetMenuLevelLabelsRequest{}
if res, err := s.GetMenuLevelLabels(ctx.Context(), req); err != nil {
if er, ok := err.(*errors.Error); ok {
return ctx.Error(er.Code, er.Message)
} else {
return ctx.Error(errors.Unavailable, err.Error())
}
} else {
return ctx.Success(res)
}
}
}
func handleAuthServiceLogin(s AuthServiceHttpServer) http.HandleFunc { func handleAuthServiceLogin(s AuthServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) { return func(ctx *http.Context) (err error) {
req := &LoginRequest{} req := &LoginRequest{}
@ -358,6 +414,12 @@ func RegisterDepartmentServiceRouter(hs *http.Server, s DepartmentServiceHttpSer
// Register handle GetDepartmentLabels route // Register handle GetDepartmentLabels route
hs.GET("/department/labels", handleDepartmentServiceGetDepartmentLabels(s)) hs.GET("/department/labels", handleDepartmentServiceGetDepartmentLabels(s))
// Register handle GetDepartmentUsers route
hs.GET("/department/users", handleDepartmentServiceGetDepartmentUsers(s))
// Register handle GetDepartmentLevelLabels route
hs.GET("/department/level-labels", handleDepartmentServiceGetDepartmentLevelLabels(s))
} }
func RegisterRoleServiceRouter(hs *http.Server, s RoleServiceHttpServer) { func RegisterRoleServiceRouter(hs *http.Server, s RoleServiceHttpServer) {
@ -373,6 +435,13 @@ func RegisterRoleServiceRouter(hs *http.Server, s RoleServiceHttpServer) {
} }
func RegisterMenuServiceRouter(hs *http.Server, s MenuServiceHttpServer) {
// Register handle GetMenuLevelLabels route
hs.GET("/menu/level-labels", handleMenuServiceGetMenuLevelLabels(s))
}
func RegisterAuthServiceRouter(hs *http.Server, s AuthServiceHttpServer) { func RegisterAuthServiceRouter(hs *http.Server, s AuthServiceHttpServer) {
// Register handle Login route // Register handle Login route

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-aeus. DO NOT EDIT. // Code generated by protoc-gen-go-aeus. DO NOT EDIT.
// source: organize.proto // source: organize.proto
// date: 2025-06-17 18:12:28 // date: 2025-06-18 14:37:24
package pb package pb
@ -12,7 +12,7 @@ type MenuModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"菜单ID"` Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"菜单ID"`
CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"创建时间" scenarios:"view;export"` CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"创建时间" scenarios:"view;export"`
UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"index" comment:"更新时间" scenarios:"view;export"` UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"index" comment:"更新时间" scenarios:"view;export"`
Parent string `json:"parent" yaml:"parent" xml:"parent" gorm:"index;size:60" comment:"父级菜单" props:"readonly:update"` Parent string `json:"parent" yaml:"parent" xml:"parent" gorm:"index;size:60" comment:"父级菜单" format:"menu" props:"readonly:update" live:"type:dropdown;url:/menu/level-labels"`
Name string `json:"name" yaml:"name" xml:"name" gorm:"index;size:60" comment:"组件名称" props:"readonly:update" rule:"unique;required"` Name string `json:"name" yaml:"name" xml:"name" gorm:"index;size:60" comment:"组件名称" props:"readonly:update" rule:"unique;required"`
Label string `json:"label" yaml:"label" xml:"label" gorm:"size:120" comment:"菜单标题" rule:"required"` Label string `json:"label" yaml:"label" xml:"label" gorm:"size:120" comment:"菜单标题" rule:"required"`
Uri string `json:"uri" yaml:"uri" xml:"uri" gorm:"size:512" comment:"菜单链接" scenarios:"create;update;view;export" rule:"required"` Uri string `json:"uri" yaml:"uri" xml:"uri" gorm:"size:512" comment:"菜单链接" scenarios:"create;update;view;export" rule:"required"`
@ -21,6 +21,7 @@ type MenuModel struct {
Hidden bool `json:"hidden" yaml:"hidden" xml:"hidden" comment:"是否隐藏" scenarios:"create;update;view;export"` Hidden bool `json:"hidden" yaml:"hidden" xml:"hidden" comment:"是否隐藏" scenarios:"create;update;view;export"`
Public bool `json:"public" yaml:"public" xml:"public" comment:"是否公开" scenarios:"create;update;view;export"` Public bool `json:"public" yaml:"public" xml:"public" comment:"是否公开" scenarios:"create;update;view;export"`
Description string `json:"description" yaml:"description" xml:"description" gorm:"size:1024" comment:"备注说明" scenarios:"create;update;view;export;list" format:"textarea"` Description string `json:"description" yaml:"description" xml:"description" gorm:"size:1024" comment:"备注说明" scenarios:"create;update;view;export;list" format:"textarea"`
Position int64 `json:"position" yaml:"position" xml:"position" comment:"排序" scenarios:"create;update"`
} }
func (m *MenuModel) TableName() string { func (m *MenuModel) TableName() string {
@ -40,6 +41,7 @@ func (m *MenuModel) FromValue(x *Menu) {
m.Hidden = x.Hidden m.Hidden = x.Hidden
m.Public = x.Public m.Public = x.Public
m.Description = x.Description m.Description = x.Description
m.Position = x.Position
} }
func (m *MenuModel) ToValue() (x *Menu) { func (m *MenuModel) ToValue() (x *Menu) {
@ -56,6 +58,7 @@ func (m *MenuModel) ToValue() (x *Menu) {
x.Hidden = m.Hidden x.Hidden = m.Hidden
x.Public = m.Public x.Public = m.Public
x.Description = m.Description x.Description = m.Description
x.Position = m.Position
return x return x
} }
@ -76,7 +79,7 @@ func (m *MenuModel) Delete(db *gorm.DB) (err error) {
} }
func (m *MenuModel) Find(db *gorm.DB, pk any) (err error) { func (m *MenuModel) Find(db *gorm.DB, pk any) (err error) {
return db.Where("description=?", pk).First(m).Error return db.Where("position=?", pk).First(m).Error
} }
func (m *MenuModel) FindOne(db *gorm.DB, query any, args ...any) (err error) { func (m *MenuModel) FindOne(db *gorm.DB, query any, args ...any) (err error) {
@ -158,7 +161,9 @@ func NewRoleModel() *RoleModel {
type PermissionModel struct { type PermissionModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"权限ID"` Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"权限ID"`
Menu string `json:"menu" yaml:"menu" xml:"menu" gorm:"index;size:60" comment:"所属菜单" rule:"required"` CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"创建时间" scenarios:"view;export"`
UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"index" comment:"更新时间" scenarios:"view;export"`
Menu string `json:"menu" yaml:"menu" xml:"menu" gorm:"index;size:60" comment:"所属菜单" format:"menu" rule:"required"`
Permission string `json:"permission" yaml:"permission" xml:"permission" gorm:"index;size:60" comment:"权限名称" rule:"required"` Permission string `json:"permission" yaml:"permission" xml:"permission" gorm:"index;size:60" comment:"权限名称" rule:"required"`
Label string `json:"label" yaml:"label" xml:"label" gorm:"size:60" comment:"权限标题" rule:"required"` Label string `json:"label" yaml:"label" xml:"label" gorm:"size:60" comment:"权限标题" rule:"required"`
} }
@ -169,6 +174,8 @@ func (m *PermissionModel) TableName() string {
func (m *PermissionModel) FromValue(x *Permission) { func (m *PermissionModel) FromValue(x *Permission) {
m.Id = x.Id m.Id = x.Id
m.CreatedAt = x.CreatedAt
m.UpdatedAt = x.UpdatedAt
m.Menu = x.Menu m.Menu = x.Menu
m.Permission = x.Permission m.Permission = x.Permission
m.Label = x.Label m.Label = x.Label
@ -177,6 +184,8 @@ func (m *PermissionModel) FromValue(x *Permission) {
func (m *PermissionModel) ToValue() (x *Permission) { func (m *PermissionModel) ToValue() (x *Permission) {
x = &Permission{} x = &Permission{}
x.Id = m.Id x.Id = m.Id
x.CreatedAt = m.CreatedAt
x.UpdatedAt = m.UpdatedAt
x.Menu = m.Menu x.Menu = m.Menu
x.Permission = m.Permission x.Permission = m.Permission
x.Label = m.Label x.Label = m.Label
@ -367,7 +376,7 @@ type DepartmentModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"ID"` Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"ID"`
CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"创建时间" scenarios:"view;export"` CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"创建时间" scenarios:"view;export"`
UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"index" comment:"更新时间" scenarios:"view;export"` UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"index" comment:"更新时间" scenarios:"view;export"`
ParentId int64 `json:"parent_id" yaml:"parentId" xml:"parentId" comment:"父级部门" format:"department"` ParentId int64 `json:"parent_id" yaml:"parentId" xml:"parentId" comment:"父级部门" format:"department" live:"type:dropdown;url:/department/level-labels"`
Name string `json:"name" yaml:"name" xml:"name" gorm:"size:20" comment:"部门名称" rule:"required"` Name string `json:"name" yaml:"name" xml:"name" gorm:"size:20" comment:"部门名称" rule:"required"`
Description string `json:"description" yaml:"description" xml:"description" gorm:"size:1024" comment:"备注说明" scenarios:"create;update;view;export;list" format:"textarea"` Description string `json:"description" yaml:"description" xml:"description" gorm:"size:1024" comment:"备注说明" scenarios:"create;update;view;export;list" format:"textarea"`
} }

View File

@ -2,12 +2,9 @@ package aeusadmin
import ( import (
"context" "context"
"fmt"
"slices" "slices"
"time"
"git.nobla.cn/golang/aeus-admin/models" "git.nobla.cn/golang/aeus-admin/internal/logic"
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
"git.nobla.cn/golang/aeus/middleware/auth" "git.nobla.cn/golang/aeus/middleware/auth"
"git.nobla.cn/golang/aeus/pkg/errors" "git.nobla.cn/golang/aeus/pkg/errors"
"gorm.io/gorm" "gorm.io/gorm"
@ -15,22 +12,9 @@ import (
type PermissionChecker struct { type PermissionChecker struct {
db *gorm.DB db *gorm.DB
logic *logic.User
} }
func (p *PermissionChecker) getUserPermissions(ctx context.Context, uid string) (permissions []string, err error) {
permissions, err = dbcache.TryCache(ctx, fmt.Sprintf("user:permissions:%s", uid), func(tx *gorm.DB) ([]string, error) {
var ss []string
err = tx.Select("permission").Model(&models.RolePermission{}).
Joins("LEFT JOIN users on users.role = role_permissions.role").
Where("users.uid = ?", uid).
Pluck("permission", &ss).
Error
return ss, err
}, dbcache.WithCacheDuration(time.Minute), dbcache.WithDB(p.db))
return
}
func (p *PermissionChecker) CheckPermission(ctx context.Context, permission string) (err error) { func (p *PermissionChecker) CheckPermission(ctx context.Context, permission string) (err error) {
var ( var (
uid string uid string
@ -43,7 +27,7 @@ func (p *PermissionChecker) CheckPermission(ctx context.Context, permission stri
return return
} }
} }
if ps, err = p.getUserPermissions(ctx, uid); err != nil { if ps, err = p.logic.GetPermissions(ctx, uid); err != nil {
return return
} }
if !slices.Contains(ps, permission) { if !slices.Contains(ps, permission) {
@ -55,5 +39,6 @@ func (p *PermissionChecker) CheckPermission(ctx context.Context, permission stri
func NewPermissionChecker(db *gorm.DB) *PermissionChecker { func NewPermissionChecker(db *gorm.DB) *PermissionChecker {
return &PermissionChecker{ return &PermissionChecker{
db: db, db: db,
logic: logic.NewUserLogic(db),
} }
} }

View File

@ -11,7 +11,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"git.nobla.cn/golang/aeus-admin/defaults" "git.nobla.cn/golang/aeus-admin/migrate"
"git.nobla.cn/golang/aeus-admin/models" "git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pkg/dbcache" "git.nobla.cn/golang/aeus-admin/pkg/dbcache"
adminTypes "git.nobla.cn/golang/aeus-admin/types" adminTypes "git.nobla.cn/golang/aeus-admin/types"
@ -100,30 +100,11 @@ func checkModelMenu(db *gorm.DB, viewPath string, apiPrefix string, model *rest.
func checkModelPermission(db *gorm.DB, menuName string, scene string, model *rest.Model, translate Translate) (permissionModel *models.Permission, err error) { func checkModelPermission(db *gorm.DB, menuName string, scene string, model *rest.Model, translate Translate) (permissionModel *models.Permission, err error) {
permissionModel = &models.Permission{} permissionModel = &models.Permission{}
permission := model.Permission(scene) permission := model.Permission(scene)
if err = db.Where("permission = ? AND menu = ?", permission, menuName).First(permissionModel).Error; err != nil { label := scene
if errors.Is(err, gorm.ErrRecordNotFound) {
permissionModel.Menu = menuName
permissionModel.Label = scene
if translate != nil { if translate != nil {
permissionModel.Label = translate.Permission(model, scene, permissionModel.Label) label = translate.Permission(model, scene, label)
}
permissionModel.Permission = permission
err = db.Create(permissionModel).Error
}
}
return
}
func replaceModelPermission(db *gorm.DB, menuName string, permission string, label string) (permissionModel *models.Permission, err error) {
permissionModel = &models.Permission{}
if err = db.Where("permission = ? AND menu = ?", permission, menuName).First(permissionModel).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
permissionModel.Menu = menuName
permissionModel.Label = label
permissionModel.Permission = permission
err = db.Create(permissionModel).Error
}
} }
permissionModel, err = migrate.Permission(db, menuName, permission, label)
return return
} }
@ -148,7 +129,7 @@ func checkModel(opts *options, model *rest.Model) (err error) {
modelValue := reflect.New(model.Value().Type()).Interface() modelValue := reflect.New(model.Value().Type()).Interface()
if v, ok := modelValue.(adminTypes.PerrmissionModule); ok { if v, ok := modelValue.(adminTypes.PerrmissionModule); ok {
for k, v := range v.ModelPermissions() { for k, v := range v.ModelPermissions() {
if _, err = replaceModelPermission(tx, menuModel.Name, k, v); err != nil { if _, err = migrate.Permission(tx, menuModel.Name, k, v); err != nil {
tx.Rollback() tx.Rollback()
return return
} }
@ -287,7 +268,6 @@ func AutoMigrate(ctx context.Context, db *gorm.DB, model any, cbs ...Option) (er
} }
func registerRESTRoute(domain string, db *gorm.DB, hs *http.Server) { func registerRESTRoute(domain string, db *gorm.DB, hs *http.Server) {
handleListSchemas := func(ctx *http.Context) (err error) { handleListSchemas := func(ctx *http.Context) (err error) {
var ( var (
schemas []*restTypes.Schema schemas []*restTypes.Schema
@ -390,7 +370,7 @@ func Init(ctx context.Context, cbs ...Option) (err error) {
registerRESTRoute(opts.domain, opts.db, opts.httpServer) registerRESTRoute(opts.domain, opts.db, opts.httpServer)
} }
if !opts.disableDefault { if !opts.disableDefault {
if err = defaults.Generate(opts.db); err != nil { if err = migrate.Default(opts.db); err != nil {
return return
} }
} }
@ -398,5 +378,8 @@ func Init(ctx context.Context, cbs ...Option) (err error) {
//启用操作记录 //启用操作记录
NewActivityRecorder(ctx, opts.db).Recoder() NewActivityRecorder(ctx, opts.db).Recoder()
} }
//注册渲染器
NewFormatter(opts.db).Register()
return return
} }

View File

@ -1,7 +1,10 @@
package service package service
import ( import (
"bytes"
"context" "context"
"encoding/json"
"net/http"
"time" "time"
"git.nobla.cn/golang/aeus-admin/models" "git.nobla.cn/golang/aeus-admin/models"
@ -20,6 +23,19 @@ type (
secret []byte secret []byte
method string method string
ttl int64 ttl int64
turnstileValidateUrl string
turnstileSiteKey string
}
turnstileRequest struct {
Secret string `json:"secret"`
Response string `json:"response"`
}
turnstileResponse struct {
Success bool `json:"success"`
Hostname string `json:"hostname"`
ErrorCodes []string `json:"error-codes"`
Action string `json:"action"`
} }
AuthOption func(o *authOptions) AuthOption func(o *authOptions)
@ -41,6 +57,16 @@ func WithAuthSecret(secret []byte) AuthOption {
} }
} }
func WithAuthTranslate(key, url string) AuthOption {
return func(o *authOptions) {
o.turnstileSiteKey = key
if url == "" {
url = "https://challenges.cloudflare.com/turnstile/v0/siteverify"
}
o.turnstileValidateUrl = url
}
}
func WithAuthMethod(method string) AuthOption { func WithAuthMethod(method string) AuthOption {
return func(o *authOptions) { return func(o *authOptions) {
o.method = method o.method = method
@ -53,12 +79,56 @@ func WithAuthTTL(ttl int64) AuthOption {
} }
} }
func (s *AuthService) turnstileValidate(ctx context.Context, token string) (err error) {
var (
buf []byte
req *http.Request
res *http.Response
)
if s.opts.turnstileSiteKey == "" || s.opts.turnstileValidateUrl == "" {
return nil
}
payload := &turnstileRequest{
Secret: s.opts.turnstileSiteKey,
Response: token,
}
if buf, err = json.Marshal(payload); err != nil {
return
}
if req, err = http.NewRequestWithContext(ctx, http.MethodPost, s.opts.turnstileValidateUrl, bytes.NewReader(buf)); err != nil {
return
}
req.Header.Set("Content-Type", "application/json")
if res, err = http.DefaultClient.Do(req); err != nil {
return
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return errors.Format(errors.Unavailable, "turnstile validate failed")
}
result := &turnstileResponse{}
if err = json.NewDecoder(res.Body).Decode(result); err != nil {
return
}
if !result.Success {
if len(result.ErrorCodes) == 0 {
err = errors.Format(errors.Unavailable, "turnstile validate failed")
} else {
err = errors.Format(errors.Unavailable, result.ErrorCodes[0])
}
}
return
}
func (s *AuthService) Login(ctx context.Context, req *pb.LoginRequest) (res *pb.LoginResponse, err error) { func (s *AuthService) Login(ctx context.Context, req *pb.LoginRequest) (res *pb.LoginResponse, err error) {
model := &models.User{} model := &models.User{}
tx := s.opts.db.WithContext(ctx) tx := s.opts.db.WithContext(ctx)
if err = req.Validate(); err != nil { if err = req.Validate(); err != nil {
return nil, errors.Format(errors.Invalid, err.Error()) return nil, errors.Format(errors.Invalid, err.Error())
} }
if err = s.turnstileValidate(ctx, req.Token); err != nil {
return nil, errors.Format(errors.Invalid, err.Error())
}
if err = model.FindOne(tx, "uid=?", req.Username); err != nil { if err = model.FindOne(tx, "uid=?", req.Username); err != nil {
return nil, errors.ErrAccessDenied return nil, errors.ErrAccessDenied
} }

View File

@ -3,10 +3,12 @@ package service
import ( import (
"context" "context"
"fmt" "fmt"
"strconv"
"git.nobla.cn/golang/aeus-admin/internal/logic"
"git.nobla.cn/golang/aeus-admin/models" "git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pb" "git.nobla.cn/golang/aeus-admin/pb"
"git.nobla.cn/golang/aeus-admin/pkg/dbcache" "git.nobla.cn/golang/rest/types"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -18,6 +20,8 @@ type (
DepartmentService struct { DepartmentService struct {
opts *departmentOptions opts *departmentOptions
logic *logic.Department
user *logic.User
} }
) )
@ -29,24 +33,87 @@ func WithDepartmentDB(db *gorm.DB) DepartmentOption {
func (s *DepartmentService) GetDepartmentLabels(ctx context.Context, req *pb.GetDepartmentLabelRequest) (res *pb.GetDepartmentLabelResponse, err error) { func (s *DepartmentService) GetDepartmentLabels(ctx context.Context, req *pb.GetDepartmentLabelRequest) (res *pb.GetDepartmentLabelResponse, err error) {
res = &pb.GetDepartmentLabelResponse{} res = &pb.GetDepartmentLabelResponse{}
res.Data, err = dbcache.TryCache(ctx, fmt.Sprintf("department:labels"), func(tx *gorm.DB) ([]*pb.DepartmentLabelValue, error) { var values []*types.TypeValue[int64]
values := make([]*models.Department, 0) if values, err = s.logic.GetLabels(ctx); err == nil {
if err = tx.Find(&values).Error; err == nil { res.Data = make([]*pb.DepartmentLabelValue, 0, len(values))
items := make([]*pb.DepartmentLabelValue, 0, len(values)) for _, row := range values {
for _, v := range values { res.Data = append(res.Data, &pb.DepartmentLabelValue{
items = append(items, &pb.DepartmentLabelValue{ Label: row.Label,
Label: v.Name, Value: row.Value,
Value: v.Id,
}) })
} }
return items, nil
} else {
return nil, err
} }
}, return
dbcache.WithDB(s.opts.db), }
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM departments")),
func (s *DepartmentService) recursiveDepartmentUser(parent int64, departments []*models.Department, users []*models.User) []*pb.DepartmentUserValue {
values := make([]*pb.DepartmentUserValue, 0, len(departments))
for _, row := range departments {
if row.ParentId == parent {
item := &pb.DepartmentUserValue{
Label: row.Name,
Value: strconv.FormatInt(row.Id, 10),
Children: make([]*pb.DepartmentUserValue, 0),
}
item.Children = append(item.Children, s.recursiveDepartmentUser(row.Id, departments, users)...)
for _, v := range users {
if v.DeptId == row.Id {
item.Children = append(item.Children, &pb.DepartmentUserValue{
Label: fmt.Sprintf("%s(%s)", v.Username, v.Uid),
Value: v.Uid,
Isuser: true,
})
}
}
values = append(values, item)
}
}
return values
}
func (s *DepartmentService) recursiveDepartmentLevel(parent int64, departments []*models.Department) []*pb.DepartmentLevelValue {
values := make([]*pb.DepartmentLevelValue, 0, len(departments))
for _, row := range departments {
if row.ParentId == parent {
item := &pb.DepartmentLevelValue{
Label: row.Name,
Value: row.Id,
Children: make([]*pb.DepartmentLevelValue, 0),
}
item.Children = append(item.Children, s.recursiveDepartmentLevel(row.Id, departments)...)
values = append(values, item)
}
}
return values
}
func (s *DepartmentService) GetDepartmentUsers(ctx context.Context, req *pb.GetDepartmentUserRequest) (res *pb.GetDepartmentUserResponse, err error) {
var (
users []*models.User
departments []*models.Department
) )
if departments, err = s.logic.GetDepartments(ctx); err != nil {
return
}
if users, err = s.user.GeUsers(ctx); err != nil {
return
}
res = &pb.GetDepartmentUserResponse{
Data: s.recursiveDepartmentUser(0, departments, users),
}
return
}
func (s *DepartmentService) GetDepartmentLevelLabels(ctx context.Context, req *pb.GetDepartmentLevelLabelsRequest) (res *pb.GetDepartmentLevelLabelsResponse, err error) {
var (
departments []*models.Department
)
if departments, err = s.logic.GetDepartments(ctx); err != nil {
return
}
res = &pb.GetDepartmentLevelLabelsResponse{
Data: s.recursiveDepartmentLevel(0, departments),
}
return return
} }
@ -57,5 +124,7 @@ func NewDepartmentService(cbs ...DepartmentOption) *DepartmentService {
} }
return &DepartmentService{ return &DepartmentService{
opts: opts, opts: opts,
user: logic.NewUserLogic(opts.db),
logic: logic.NewDepartmentLogic(opts.db),
} }
} }

68
service/menu.go 100644
View File

@ -0,0 +1,68 @@
package service
import (
"context"
"git.nobla.cn/golang/aeus-admin/internal/logic"
"git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pb"
"gorm.io/gorm"
)
type (
menuOptions struct {
db *gorm.DB
}
MenuOption func(o *menuOptions)
MenuService struct {
opts *menuOptions
logic *logic.Menu
}
)
func WithMenuDB(db *gorm.DB) MenuOption {
return func(o *menuOptions) {
o.db = db
}
}
func (s *MenuService) recursiveMenuLevel(parent string, items []*models.Menu) []*pb.MenuLevelValue {
values := make([]*pb.MenuLevelValue, 0, len(items))
for _, row := range items {
if row.Parent == parent {
item := &pb.MenuLevelValue{
Label: row.Label,
Value: row.Name,
Children: make([]*pb.MenuLevelValue, 0),
}
item.Children = append(item.Children, s.recursiveMenuLevel(row.Name, items)...)
values = append(values, item)
}
}
return values
}
func (s *MenuService) GetMenuLevelLabels(ctx context.Context, req *pb.GetMenuLevelLabelsRequest) (res *pb.GetMenuLevelLabelsResponse, err error) {
var (
items []*models.Menu
)
if items, err = s.logic.GetMenus(ctx); err != nil {
return
}
res = &pb.GetMenuLevelLabelsResponse{
Data: s.recursiveMenuLevel("", items),
}
return
}
func NewMenuService(cbs ...MenuOption) *MenuService {
opts := &menuOptions{}
for _, cb := range cbs {
cb(opts)
}
return &MenuService{
opts: opts,
logic: logic.NewMenuLogic(opts.db),
}
}

View File

@ -2,11 +2,11 @@ package service
import ( import (
"context" "context"
"fmt"
"git.nobla.cn/golang/aeus-admin/internal/logic"
"git.nobla.cn/golang/aeus-admin/models" "git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pb" "git.nobla.cn/golang/aeus-admin/pb"
"git.nobla.cn/golang/aeus-admin/pkg/dbcache" "git.nobla.cn/golang/rest/types"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -18,6 +18,7 @@ type (
RoleService struct { RoleService struct {
opts *roleOptions opts *roleOptions
logic *logic.Role
} }
) )
@ -29,24 +30,16 @@ func WithRoleDB(db *gorm.DB) RoleOption {
func (s *RoleService) GetRoleLabels(ctx context.Context, req *pb.GetRoleLabelRequest) (res *pb.GetRoleLabelResponse, err error) { func (s *RoleService) GetRoleLabels(ctx context.Context, req *pb.GetRoleLabelRequest) (res *pb.GetRoleLabelResponse, err error) {
res = &pb.GetRoleLabelResponse{} res = &pb.GetRoleLabelResponse{}
res.Data, err = dbcache.TryCache(ctx, fmt.Sprintf("role:labels"), func(tx *gorm.DB) ([]*pb.LabelValue, error) { var values []*types.TypeValue[string]
values := make([]*models.Role, 0) if values, err = s.logic.GetLabels(ctx); err == nil {
if err = tx.Find(&values).Error; err == nil { res.Data = make([]*pb.LabelValue, 0, len(values))
items := make([]*pb.LabelValue, 0, len(values)) for _, row := range values {
for _, v := range values { res.Data = append(res.Data, &pb.LabelValue{
items = append(items, &pb.LabelValue{ Label: row.Label,
Label: v.Label, Value: row.Value,
Value: v.Name,
}) })
} }
return items, nil
} else {
return nil, err
} }
},
dbcache.WithDB(s.opts.db),
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM roles")),
)
return return
} }
@ -90,5 +83,6 @@ func NewRoleService(cbs ...RoleOption) *RoleService {
} }
return &RoleService{ return &RoleService{
opts: opts, opts: opts,
logic: logic.NewRoleLogic(opts.db),
} }
} }

View File

@ -3,13 +3,16 @@ package service
import ( import (
"context" "context"
"fmt" "fmt"
"strconv"
"time" "time"
"git.nobla.cn/golang/aeus-admin/internal/logic"
"git.nobla.cn/golang/aeus-admin/models" "git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pb" "git.nobla.cn/golang/aeus-admin/pb"
"git.nobla.cn/golang/aeus-admin/pkg/dbcache" "git.nobla.cn/golang/aeus-admin/pkg/dbcache"
"git.nobla.cn/golang/aeus/middleware/auth" "git.nobla.cn/golang/aeus/middleware/auth"
"git.nobla.cn/golang/aeus/pkg/errors" "git.nobla.cn/golang/aeus/pkg/errors"
"git.nobla.cn/golang/rest/types"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -21,6 +24,10 @@ type (
UserOption func(o *userOptions) UserOption func(o *userOptions)
UserService struct { UserService struct {
user *logic.User
menu *logic.Menu
role *logic.Role
department *logic.Department
opts *userOptions opts *userOptions
} }
) )
@ -87,12 +94,6 @@ func (s *UserService) recursiveNestedMenu(ctx context.Context, parent string, pe
return values return values
} }
func (s *UserService) getRolePermissions(db *gorm.DB, role string) (permissions []*models.Permission, err error) {
permissions = make([]*models.Permission, 0)
err = db.Where("permission IN (SELECT permission FROM role_permissions WHERE role = ?)", role).Find(&permissions).Error
return
}
func (s *UserService) GetMenus(ctx context.Context, req *pb.GetMenuRequest) (res *pb.GetMenuResponse, err error) { func (s *UserService) GetMenus(ctx context.Context, req *pb.GetMenuRequest) (res *pb.GetMenuResponse, err error) {
var ( var (
uid string uid string
@ -103,28 +104,28 @@ func (s *UserService) GetMenus(ctx context.Context, req *pb.GetMenuRequest) (res
} }
res = &pb.GetMenuResponse{} res = &pb.GetMenuResponse{}
res.Data, err = dbcache.TryCache(ctx, fmt.Sprintf("user:menu:%s:%v", uid, req.Permission), func(tx *gorm.DB) ([]*pb.MenuItem, error) { res.Data, err = dbcache.TryCache(ctx, fmt.Sprintf("user:menu:%s:%v", uid, req.Permission), func(tx *gorm.DB) ([]*pb.MenuItem, error) {
userModel := &models.User{} var (
userModel *models.User
menus []*models.Menu
)
userModel = &models.User{}
if err = tx.Where("uid=?", uid).First(userModel).Error; err != nil { if err = tx.Where("uid=?", uid).First(userModel).Error; err != nil {
return nil, err return nil, err
} }
items := make([]*models.Menu, 0) if menus, err = s.menu.GetMenus(ctx); err != nil {
if err = tx.Find(&items).Error; err != nil {
return nil, err return nil, err
} }
roleName := userModel.Role
if userModel.Admin { if userModel.Admin {
permissions = make([]*models.Permission, 0) roleName = ""
if err = tx.Find(&permissions).Error; err != nil { }
if permissions, err = s.role.GetPermissions(ctx, roleName); err != nil {
return nil, err return nil, err
} }
} else { return s.recursiveNestedMenu(ctx, "", req.Permission, menus, permissions), nil
if permissions, err = s.getRolePermissions(tx, userModel.Role); err != nil {
return nil, err
}
}
return s.recursiveNestedMenu(ctx, "", req.Permission, items, permissions), nil
}, },
dbcache.WithDB(s.opts.db), dbcache.WithDB(s.opts.db),
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT `updated_at` FROM users WHERE `uid`=?", uid)), dbcache.WithCacheDuration(time.Second*10),
) )
return return
} }
@ -145,7 +146,6 @@ func (s *UserService) GetProfile(ctx context.Context, req *pb.GetProfileRequest)
}, },
dbcache.WithDB(s.opts.db), dbcache.WithDB(s.opts.db),
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT `updated_at` FROM users WHERE `uid`=?", req.Uid)), dbcache.WithDependency(dbcache.NewSqlDependency("SELECT `updated_at` FROM users WHERE `uid`=?", req.Uid)),
// dbcache.WithDepend("SELECT `updated_at` FROM users WHERE `uid`=?", req.Uid),
) )
return return
} }
@ -213,41 +213,59 @@ func (s *UserService) GetPermissions(ctx context.Context, req *pb.GetPermissionR
res = &pb.GetPermissionResponse{ res = &pb.GetPermissionResponse{
Uid: req.Uid, Uid: req.Uid,
} }
res.Permissions, err = dbcache.TryCache(ctx, fmt.Sprintf("user:permissions:%s", req.Uid), func(tx *gorm.DB) ([]string, error) { res.Permissions, err = s.user.GetPermissions(ctx, req.Uid)
var ss []string
err = tx.Select("permission").Model(&models.RolePermission{}).
Joins("LEFT JOIN users on users.role = role_permissions.role").
Where("users.uid = ?", req.Uid).
Pluck("permission", &ss).
Error
return ss, err
}, dbcache.WithCacheDuration(time.Minute), dbcache.WithDB(s.opts.db))
return return
} }
func (s *UserService) GetUserLabels(ctx context.Context, req *pb.GetUserLabelRequest) (res *pb.GetUserLabelResponse, err error) { func (s *UserService) GetUserLabels(ctx context.Context, req *pb.GetUserLabelRequest) (res *pb.GetUserLabelResponse, err error) {
res = &pb.GetUserLabelResponse{} res = &pb.GetUserLabelResponse{}
res.Data, err = dbcache.TryCache(ctx, fmt.Sprintf("user:labels"), func(tx *gorm.DB) ([]*pb.LabelValue, error) { var values []*types.TypeValue[string]
values := make([]*models.User, 0) if values, err = s.user.GetLabels(ctx); err == nil {
if err = tx.Find(&values).Error; err == nil { res.Data = make([]*pb.LabelValue, 0, len(values))
items := make([]*pb.LabelValue, 0, len(values)) for _, row := range values {
for _, v := range values { res.Data = append(res.Data, &pb.LabelValue{
items = append(items, &pb.LabelValue{ Label: row.Label,
Label: v.Username, Value: row.Value,
Value: v.Uid,
}) })
} }
return items, nil
} else {
return nil, err
} }
},
dbcache.WithDB(s.opts.db),
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM users")),
)
return return
} }
func (s *UserService) DepartmentUserNested(ctx context.Context) []*types.NestedValue[string] {
var (
err error
users []*models.User
departments []*models.Department
)
if departments, err = s.department.GetDepartments(ctx); err != nil {
return nil
}
if users, err = s.user.GeUsers(ctx); err != nil {
return nil
}
depts := s.department.RecursiveDepartment(ctx, 0, 0, departments)
values := make([]*types.NestedValue[string], 0)
for _, dept := range depts {
v := &types.NestedValue[string]{
Label: dept.Label,
Value: strconv.FormatInt(dept.Value, 10),
Children: make([]*types.NestedValue[string], 0),
}
for _, user := range users {
if strconv.FormatInt(user.DeptId, 10) == v.Value {
v.Children = append(v.Children, &types.NestedValue[string]{
Label: fmt.Sprintf("%s(%s)", user.Username, user.Uid),
Value: user.Uid,
})
}
}
values = append(values, v)
}
return values
}
func (s *UserService) GetUserTags(ctx context.Context, req *pb.GetUserTagRequest) (res *pb.GetUserTagResponse, err error) { func (s *UserService) GetUserTags(ctx context.Context, req *pb.GetUserTagRequest) (res *pb.GetUserTagResponse, err error) {
res = &pb.GetUserTagResponse{} res = &pb.GetUserTagResponse{}
res.Data, err = dbcache.TryCache(ctx, fmt.Sprintf("user:tags"), func(tx *gorm.DB) ([]*pb.LabelValue, error) { res.Data, err = dbcache.TryCache(ctx, fmt.Sprintf("user:tags"), func(tx *gorm.DB) ([]*pb.LabelValue, error) {
@ -281,5 +299,9 @@ func NewUserService(cbs ...UserOption) *UserService {
} }
return &UserService{ return &UserService{
opts: opts, opts: opts,
user: logic.NewUserLogic(opts.db),
role: logic.NewRoleLogic(opts.db),
menu: logic.NewMenuLogic(opts.db),
department: logic.NewDepartmentLogic(opts.db),
} }
} }