feat: menu device

This commit is contained in:
louis 2024-04-10 17:39:17 +08:00
parent 2df310b1c0
commit 563c08c233
11 changed files with 83 additions and 18 deletions

View File

@ -40,3 +40,9 @@ export enum HasInventoryStatusEnum {
Yes = 1, // 有库存
No = 2 // 无库存
}
// 权限资源设备类型
export enum ResourceDeviceEnum {
APP = 0,
PC = 1
}

View File

@ -132,8 +132,8 @@ export class AuthService {
/**
*
*/
async getMenus(uid: number): Promise<string[]> {
return this.menuService.getMenus(uid);
async getMenus(uid: number, isApp: number): Promise<string[]> {
return this.menuService.getMenus(uid,isApp);
}
/**

View File

@ -14,6 +14,8 @@ import { UserService } from '../../user/user.service';
import { AuthService } from '../auth.service';
import { AccountMenus, AccountUpdateDto } from '../dto/account.dto';
import { JwtAuthGuard } from '../guards/jwt-auth.guard';
import { IsMobile } from '~/common/decorators/http.decorator';
import { ResourceDeviceEnum } from '~/constants/enum';
@ApiTags('Account - 账户模块')
@ApiSecurityAuth()
@ -45,8 +47,11 @@ export class AccountController {
@ApiOperation({ summary: '获取菜单列表' })
@ApiResult({ type: [AccountMenus] })
@AllowAnon()
async menu(@AuthUser() user: IAuthUser): Promise<string[]> {
return this.authService.getMenus(user.uid);
async menu(@AuthUser() user: IAuthUser, @IsMobile() isApp: boolean): Promise<string[]> {
return this.authService.getMenus(
user.uid,
isApp ? ResourceDeviceEnum.APP : ResourceDeviceEnum.PC
);
}
@Get('permissions')

View File

@ -53,6 +53,9 @@ export class MaterialsInOutDto {
inOrOut: MaterialsInOrOutEnum;
@ApiProperty({ description: '时间' })
@Transform(params => {
return params.value ? new Date(params.value) : null;
})
@IsOptional()
time: Date;

View File

@ -23,6 +23,8 @@ import {
import { MenuDto, MenuQueryDto, MenuUpdateDto } from './menu.dto';
import { MenuItemInfo } from './menu.model';
import { MenuService } from './menu.service';
import { IsMobile } from '~/common/decorators/http.decorator';
import { ResourceDeviceEnum } from '~/constants/enum';
export const permissions = definePermission('system:menu', {
LIST: 'list',
@ -43,7 +45,9 @@ export class MenuController {
@ApiResult({ type: [MenuItemInfo] })
@Perm(permissions.LIST)
async list(@Query() dto: MenuQueryDto) {
return this.menuService.list(dto);
return this.menuService.list({
...dto
});
}
@Get(':id')

View File

@ -3,6 +3,7 @@ import {
IsBoolean,
IsIn,
IsInt,
IsNumber,
IsOptional,
IsString,
Min,
@ -15,6 +16,11 @@ export class MenuDto {
@IsIn([0, 1, 2])
type: number;
@ApiProperty({ description: '客户端设备类型' })
@IsOptional()
@IsIn([0, 1])
device: number;
@ApiProperty({ description: '父级菜单' })
@IsOptional()
parentId: number;
@ -85,4 +91,11 @@ export class MenuDto {
export class MenuUpdateDto extends PartialType(MenuDto) {}
export class MenuQueryDto extends PartialType(MenuDto) {}
export class MenuQueryDto extends PartialType(MenuDto) {
@ApiProperty({ description: 'App端的菜单权限' })
@IsNumber()
@IsOptional()
isApp?: number;
}

View File

@ -6,28 +6,28 @@ import { RoleEntity } from '../role/role.entity';
@Entity({ name: 'sys_menu' })
export class MenuEntity extends CommonEntity {
@Column({ name: 'parent_id', nullable: true })
@Column({ name: 'parent_id', nullable: true, comment: '父级ID' })
parentId: number;
@Column()
name: string;
@Column({ nullable: true })
@Column({ nullable: true, comment: '前端路径' })
path: string;
@Column({ nullable: true })
@Column({ nullable: true, comment: '权限' })
permission: string;
@Column({ type: 'tinyint', default: 0 })
@Column({ type: 'tinyint', default: 0, comment: '类型0-目录 1-菜单 2-权限' })
type: number;
@Column({ nullable: true, default: '' })
@Column({ nullable: true, default: '', comment: '图标' })
icon: string;
@Column({ name: 'order_no', type: 'int', nullable: true, default: 0 })
orderNo: number;
@Column({ name: 'component', nullable: true })
@Column({ name: 'component', nullable: true, comment: '前端组件文件地址' })
component: string;
@Column({ name: 'is_ext', type: 'boolean', default: false })
@ -48,6 +48,9 @@ export class MenuEntity extends CommonEntity {
@Column({ type: 'tinyint', default: 1 })
status: number;
@Column({ type: 'tinyint', default: 1,comment: '用户端类型0-APP 1-PC' })
device: number;
@ManyToMany(() => RoleEntity, role => role.menus, {
onDelete: 'CASCADE'
})

View File

@ -18,6 +18,7 @@ import { deleteEmptyChildren, generatorMenu, generatorRouters } from '~/utils';
import { RoleService } from '../role/role.service';
import { MenuDto, MenuQueryDto, MenuUpdateDto } from './menu.dto';
import { ResourceDeviceEnum } from '~/constants/enum';
@Injectable()
export class MenuService {
@ -32,7 +33,14 @@ export class MenuService {
/**
*
*/
async list({ name, path, permission, component, status }: MenuQueryDto): Promise<MenuEntity[]> {
async list({
name,
path,
permission,
component,
status,
isApp
}: MenuQueryDto): Promise<MenuEntity[]> {
const menus = await this.menuRepository.find({
where: {
...(name && { name: Like(`%${name}%`) }),
@ -66,20 +74,29 @@ export class MenuService {
/**
*
*/
async getMenus(uid: number): Promise<string[]> {
async getMenus(uid: number, deviceType: number): Promise<string[]> {
const roleIds = await this.roleService.getRoleIdsByUser(uid);
let menus: MenuEntity[] = [];
if (isEmpty(roleIds)) return generatorRouters([]);
if (this.roleService.hasAdminRole(roleIds)) {
menus = await this.menuRepository.find({ order: { orderNo: 'ASC' } });
menus = await this.menuRepository.find({
order: { orderNo: 'ASC' },
where: {
...(isNumber(deviceType) ? { device: deviceType } : null)
}
});
} else {
menus = await this.menuRepository
.createQueryBuilder('menu')
.innerJoinAndSelect('menu.roles', 'role')
.where({
...(isNumber(deviceType) ? { device: deviceType } : null)
})
.andWhere('role.id IN (:...roleIds)', { roleIds })
.orderBy('menu.order_no', 'ASC')
.getMany();
}

View File

@ -35,4 +35,9 @@ export class RoleQueryDto extends IntersectionType(PagerDto<RoleDto>, PartialTyp
@IsInt()
@IsOptional()
status?: number;
@ApiProperty({ description: '用于下拉框选择', required: false })
@IsInt()
@IsOptional()
useForSelect: number;
}

View File

@ -32,14 +32,17 @@ export class RoleService {
pageSize,
name,
value,
status
status,
useForSelect
}: RoleQueryDto): Promise<Pagination<RoleEntity>> {
const queryBuilder = this.roleRepository.createQueryBuilder('role').where({
...(name ? { name: Like(`%${name}%`) } : null),
...(value ? { value: Like(`%${value}%`) } : null),
...(isNumber(status) ? { status } : null)
});
if(useForSelect){
queryBuilder.andWhere('role.id != :id', { id: ROOT_ROLE_ID })
}
return paginate<RoleEntity>(queryBuilder, {
page,
pageSize

View File

@ -268,7 +268,13 @@ export class UserService {
if (keyword) {
//关键字模糊查询product的name,productNumber,productSpecification
queryBuilder.andWhere(
'(user.nickname like :keyword or user.namePinyin like :keyword or dept.name like :keyword)',
`(user.nickname like :keyword or user.namePinyin like :keyword
or dept.name like :keyword
or user.phone like :keyword
or user.email like :keyword
or user.qq like :keyword
or user.remark like :keyword
)`,
{
keyword: `%${keyword}%`
}