import { Injectable } from '@nestjs/common'; import { Subscriber } from 'rxjs'; import { In } from 'typeorm'; import { ROOT_ROLE_ID } from '~/constants/system.constant'; import { RoleEntity } from '~/modules/system/role/role.entity'; import { UserEntity } from '~/modules/user/user.entity'; export interface MessageEvent { data?: string | object; id?: string; type?: 'ping' | 'close' | 'updatePermsAndMenus'; retry?: number; } const clientMap: Map> = new Map(); @Injectable() export class SseService { addClient(uid: number, subscriber: Subscriber) { clientMap.set(uid, subscriber); } removeClient(uid: number): void { const client = clientMap.get(uid); client?.complete(); clientMap.delete(uid); } sendToClient(uid: number, data: MessageEvent): void { const client = clientMap.get(uid); client?.next?.(data); } sendToAll(data: MessageEvent): void { clientMap.forEach(client => { client.next(data); }); } /** * 通知前端重新获取权限菜单 * @param uid * @constructor */ async noticeClientToUpdateMenusByUserIds(uid: number | number[]) { const userIds = [].concat(uid) as number[]; userIds.forEach(uid => { this.sendToClient(uid, { type: 'updatePermsAndMenus' }); }); } /** * 通过menuIds通知用户更新权限菜单 */ async noticeClientToUpdateMenusByMenuIds(menuIds: number[]): Promise { const roleMenus = await RoleEntity.find({ where: { menus: { id: In(menuIds) } } }); const roleIds = roleMenus.map(n => n.id).concat(ROOT_ROLE_ID); await this.noticeClientToUpdateMenusByRoleIds(roleIds); } /** * 通过roleIds通知用户更新权限菜单 */ async noticeClientToUpdateMenusByRoleIds(roleIds: number[]): Promise { const users = await UserEntity.find({ where: { roles: { id: In(roleIds) } } }); if (users) { const userIds = users.map(n => n.id); await this.noticeClientToUpdateMenusByUserIds(userIds); } } }