import { Inject, Provide } from '@midwayjs/decorator'; import { InjectEntityModel } from '@midwayjs/typegoose'; import { ReturnModelType } from '@typegoose/typegoose'; import { BaseService, PageOptions, SearchBase } from 'free-midway-component'; import { Chat } from '../entity/chat.entity'; import { cloneDeep, get, head } from 'lodash'; import { ChatMqService } from './chatMq.service'; import { Types } from 'mongoose'; import { JwtService } from '@midwayjs/jwt'; const assert = require('assert'); const ObjectId = Types.ObjectId; type modelType = ReturnModelType; @Provide() export class ChatService extends BaseService { @InjectEntityModel(Chat) model: modelType; @Inject() chatMqService: ChatMqService; @Inject() jwtService: JwtService; // 处理已读问题 async allRead(data) { const token = get(this.ctx, 'request.header.token'); assert(token, '缺少token信息'); const tokenInfo = await this.jwtService.decodeSync(token); const info = { ...data, not_read: 1, speaker: { $ne: get(tokenInfo, '_id') } }; let result; if (get(tokenInfo, 'role') === 'Patient') result = await this.model.find({ ...info }).lean(); else result = await this.model.find({ ...info, speaker_type: 'Patient' }).lean(); const ids = result.map(i => new ObjectId(i._id).toString()); await this.model.updateMany({ _id: ids }, { $set: { not_read: 0 } }); } async sendMq(data) { // 队列: /${群组id}/${患者id} const { group, patient, _id } = data; // 没有群组&患者id直接返回,无法构成队列 if (!(group && patient)) return; const routingKey = `${group}_${patient}`; const nd = await this.fetch(_id); await this.chatMqService.sendExMsg(routingKey, JSON.stringify(nd)); } async query(filter: SearchBase, pageOptions: PageOptions = {}): Promise> { const dup = cloneDeep(filter.getFilter()); const data = await this.model.find(dup, {}, { ...pageOptions, sort: { 'meta.createdAt': -1 } }).populate('speaker'); return data; } lastChatRecordListItem = { group: 1, doctor: 1, patient: 1, patientName: '$pInfo.name', patientIcon: '$pInfo.icon', type: 1, time: 1, content: 1, notRead: 1, }; /** * 根据医护.查找最后发送消息记录 * @param doctor 医生id * @param skip 分页 * @param limit 分页 * @param name 患者姓名,查询用 * @returns */ async getLastChatRecordList(doctor: string, skip?: number, limit?: number, name?: string) { const pipes = []; const query = { doctor }; pipes.push({ $match: query }); pipes.push({ $sort: { 'meta.createdAt': -1 } }); // 如果speaker等于patient,说明这是患者讲的话,是否未读的状态是算医护上的;如果不是患者讲的,那就不算了 pipes.push({ $addFields: { countDot: { $cond: { if: { $eq: ['$speaker', '$patient'] }, then: '$not_read', else: 0 } } }, }); pipes.push({ $group: { _id: '$patient', l: { $first: '$$ROOT' }, notRead: { $sum: '$countDot' }, }, }); // 将notRead结果放到l里,之后替换根变量 pipes.push({ $addFields: { 'l.gid': { $toObjectId: '$l.group' }, 'l.pid': { $toObjectId: '$l.patient' }, 'l.did': { $toObjectId: '$l.doctor' }, 'l.notRead': '$notRead' } }); pipes.push({ $replaceRoot: { newRoot: '$l' } }); pipes.push({ $lookup: { from: 'group', localField: 'gid', foreignField: '_id', as: 'gInfo', }, }); pipes.push({ $unwind: '$gInfo' }); pipes.push({ $lookup: { from: 'patient', localField: 'pid', foreignField: '_id', as: 'pInfo', }, }); pipes.push({ $unwind: '$pInfo' }); pipes.push({ $lookup: { from: 'doctor', localField: 'did', foreignField: '_id', as: 'dInfo', }, }); pipes.push({ $unwind: '$dInfo' }); if (name) { pipes.push({ $match: { 'pInfo.name': new RegExp(name) } }); } pipes.push({ $project: this.lastChatRecordListItem }); // 查询总数 const totalResult = await this.model.aggregate([...pipes, { $count: 'total' }]); if (skip && skip >= 0) pipes.push({ $skip: skip }); if (limit && limit > 0) pipes.push({ $limit: limit }); const result = await this.model.aggregate(pipes); return { data: result, total: get(head(totalResult), 'total') }; } }