import { EntityManager, getEntityManager, Query } from "relaen"; import { NfGroup } from "./entity/nfgroup"; import { NfGroupUser } from "./entity/nfgroupuser"; import { NfNode } from "./entity/nfnode"; import { NfProcess } from "./entity/nfprocess"; import { NfUser } from "./entity/nfuser"; import { NFTaskUtil } from "./taskutil"; /** * 用户与组:维护关系,并按用户查询待办 / 已办 / 发起的流程。 */ export class NFUserManager{ /** * 添加用户,可选同时加入若干组。 * * @param userId - 用户 id * @param userName - 用户名 * @param realName - 真实姓名 * @param groupIds - 组 id 数组 * @returns 已保存的用户实体 */ static async addUser(userId,userName,realName?:string,groupIds?:number[]){ const user:NfUser = new NfUser(userId); user.userName = userName; user.realName = realName; await user.save(); if(groupIds){ await this.setUserGroup(userId,groupIds); } return user; } /** * 添加组。 * * @param groupId - 组 id * @param groupName - 组名 * @returns 已保存的组实体 */ static async addGroup(groupId,groupName){ const group:NfGroup = new NfGroup(groupId); group.groupName = groupName; return await group.save(); } /** * 覆盖设置用户所属组(先清空再写入)。 * * @param userId - 用户 id * @param groupIds - 组 id 或数组;用户不存在时直接返回 */ static async setUserGroup(userId,groupIds:number|number[]){ const em:EntityManager = await getEntityManager(); const user = await NfUser.find(userId); if(!user){ return; } await NfGroupUser.deleteMany({user:userId}); if(!Array.isArray(groupIds)){ groupIds = [groupIds]; } for(let id of groupIds){ let gu:NfGroupUser = new NfGroupUser(); gu.nfUser = user; gu.nfGroup = new NfGroup(id); await gu.save(); } } /** * 按组 id 查询组成员的用户 id。 * * @param groupIds - 组 id、逗号串或数组 * @returns 用户 id 数组;无匹配时为空数组 */ static async getUserIdsByGroupIds(groupIds:string|number|number[]):Promise{ const ids = NFTaskUtil.parseIdList(groupIds); if(ids.length === 0){ return []; } const em:EntityManager = await getEntityManager(); const query:Query = em.createQuery(NfGroupUser.name); const rows = await query.select('nfUser.userId') .where({'nfGroup.groupId':{rel:'in',value:ids}}) .getResultList(); const users:number[] = []; for(let r of rows){ if(r.nfUser){ users.push(r.nfUser.userId); } } await em.close(); return users; } /** * 查询用户所属组 id。 * * @param userId - 用户 id * @returns 组 id 数组 */ static async getGroupIdsByUserId(userId:number):Promise{ const em:EntityManager = await getEntityManager(); const query:Query = em.createQuery(NfGroupUser.name); const rows = await query.select(['nfGroup.groupId']) .where({nfUser:userId}) .getResultList(); const gids:number[] = []; for(let r of rows){ if(r.nfGroup?.groupId != null){ gids.push(r.nfGroup.groupId); } } await em.close(); return gids; } /** * 查询用户待办节点。 * * 包含已指派给该用户,或尚未指派且在候选人 / 候选组中的任务。 * 已关闭实例不会出现(关闭时会结束未完成节点)。 * * @param userId - 用户 id * @param pageNo - 页号(从 1 起);与 `pageSize` 同时大于 0 时分页 * @param pageSize - 每页条数 * @returns `{ total, rows }`,`rows` 为节点实体数组 */ public static async getUnHandleNodes(userId:number,pageNo?:number,pageSize?:number):Promise{ const groupIds = await this.getGroupIdsByUserId(userId); const params:any[] = [{ candidateUsers:{rel:'like',value:','+userId+','}, endTime:null }]; for(const gid of groupIds){ params.push({ endTime:null, assignee:null, candidateGroups:{rel:'like',value:','+gid+','} }); } const seen = new Set(); let rows:NfNode[] = []; for(const param of params){ const part = await this.getNodes(param); for(const n of part.rows || []){ if(seen.has(n.nodeId)){ continue; } seen.add(n.nodeId); rows.push(n); } } rows = rows.filter(n=>!n.nfProcess?.deleteTime && NFTaskUtil.isCandidate(n, userId, groupIds)); const total = rows.length; if(pageNo>0 && pageSize>0){ const start = (pageNo-1) * pageSize; rows = rows.slice(start, start + pageSize); } return {total, rows}; } /** * 查询用户已办理的节点。 * * @param userId - 用户 id * @param pageNo - 页号 * @param pageSize - 每页条数 * @returns `{ total, rows }` */ public static async getHandledNodes(userId:number,pageNo?:number,pageSize?:number):Promise{ return await this.getNodes({ nfUser:userId },pageNo,pageSize) } /** * 按条件查询节点并附带流程、附件。 * * @param param - Relaen 查询条件 * @param pageNo - 页号 * @param pageSize - 每页条数 * @returns `{ total, rows }` */ private static async getNodes(param:any,pageNo?:number,pageSize?:number){ const em:EntityManager = await getEntityManager(); const query:Query = em.createQuery(NfNode.name); let start = 0; if(pageNo>0 && pageSize>0){ start = (pageNo-1) * pageSize; } const nodes = await query.select(['*','nfProcess.*']).where(param).getResultList(start,pageSize); const total = await em.getCount(NfNode.name,param); for(let n of nodes){ await n.getNfResources(); } await em.close(); return {total:total,rows:nodes} } /** * 查询用户发起的流程实例。 * * @param userId - 用户 id * @param pageNo - 页号 * @param pageSize - 每页条数 * @returns `{ total, rows }`,`rows` 为流程实例实体 */ public static async getCreatedProcess(userId:number,pageNo?:number,pageSize?:number):Promise{ const em:EntityManager = await getEntityManager(); const query:Query = em.createQuery(NfProcess.name); const param = { nfUser:userId } let start = 0; if(pageNo>0 && pageSize>0){ start = (pageNo-1) * pageSize; } const nodes = await query.select(['*']).where(param).getResultList(start,pageSize); const total = await em.getCount(NfProcess.name,param); await em.close(); return {total:total,rows:nodes} } }