2025-09-30
未读变已读 查询列表排序
This commit is contained in:
@@ -1,2 +1,3 @@
|
|||||||
export * from './programGroup.controller';
|
export * from './programGroup.controller';
|
||||||
export * from './file.controller';
|
export * from './file.controller';
|
||||||
|
export * from './message.controller'
|
||||||
23
src/controller/message.controller.ts
Normal file
23
src/controller/message.controller.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import {Body, Controller, Get, Post, Query} from "@nestjs/common";
|
||||||
|
import {MessageService} from "../service";
|
||||||
|
import {ProgramGroupMessageEntity, ReadDto} from "../entity";
|
||||||
|
|
||||||
|
@Controller('message')
|
||||||
|
export class MessageController {
|
||||||
|
|
||||||
|
constructor(private messageService: MessageService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取未读消息
|
||||||
|
@Get("unread")
|
||||||
|
async getUnread(@Query() readDto: ReadDto) {
|
||||||
|
return await this.messageService.getUnread(readDto)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将未读消息置为已读
|
||||||
|
@Post('read')
|
||||||
|
async read(@Body() readDto: ReadDto) {
|
||||||
|
return await this.messageService.read(readDto)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -26,5 +26,4 @@ export class ProgramGroupController {
|
|||||||
async getOne(@Param() programGroup: ProgramGroupEntity) {
|
async getOne(@Param() programGroup: ProgramGroupEntity) {
|
||||||
return await this.programGroupService.getOne(programGroup);
|
return await this.programGroupService.getOne(programGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
4
src/entity/dto/read.dto.ts
Normal file
4
src/entity/dto/read.dto.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export class ReadDto {
|
||||||
|
groupId: number;
|
||||||
|
userId: number;
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
export * from './program.entity';
|
export * from './program.entity';
|
||||||
export * from './users.entity';
|
export * from './users.entity';
|
||||||
export * from './programGroup.entity';
|
export * from './programGroup.entity';
|
||||||
export * from './programGroupMessage.entity';
|
export * from './programGroupMessage.entity';
|
||||||
|
|
||||||
|
export * from './dto/read.dto'
|
||||||
@@ -1,32 +1,36 @@
|
|||||||
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
import {Column, Entity, PrimaryGeneratedColumn} from "typeorm";
|
||||||
import {ProgramEntity} from "./program.entity";
|
import {ProgramEntity} from "./program.entity";
|
||||||
|
|
||||||
@Entity("program_group", { schema: "test" })
|
@Entity("program_group", {schema: "test"})
|
||||||
export class ProgramGroupEntity {
|
export class ProgramGroupEntity {
|
||||||
@PrimaryGeneratedColumn({ type: "int", name: "group_id", comment: "群组ID" })
|
@PrimaryGeneratedColumn({type: "int", name: "group_id", comment: "群组ID"})
|
||||||
groupId: number;
|
groupId: number;
|
||||||
|
|
||||||
@Column("int", { name: "program_id", comment: "项目ID" })
|
@Column("int", {name: "program_id", comment: "项目ID"})
|
||||||
programId: number;
|
programId: number;
|
||||||
|
|
||||||
@Column("int", { name: "charge_id", comment: "负责人ID" })
|
@Column("int", {name: "charge_id", comment: "负责人ID"})
|
||||||
chargeId: number;
|
chargeId: number;
|
||||||
|
|
||||||
@Column("int", { name: "customer_id", comment: "客服ID" })
|
@Column("int", {name: "customer_id", comment: "客服ID"})
|
||||||
customerId: number;
|
customerId: number;
|
||||||
|
|
||||||
@Column("int", { name: "user_id", comment: "用户ID" })
|
@Column("int", {name: "user_id", comment: "用户ID"})
|
||||||
userId: number;
|
userId: number;
|
||||||
|
|
||||||
@Column("datetime", {
|
@Column("datetime", {
|
||||||
name: "create_time",
|
name: "create_time",
|
||||||
comment: "创建时间",
|
comment: "创建时间",
|
||||||
default: () => "CURRENT_TIMESTAMP",
|
default: () => "CURRENT_TIMESTAMP",
|
||||||
})
|
})
|
||||||
createTime: Date;
|
createTime: Date;
|
||||||
|
|
||||||
program: ProgramEntity;
|
// 虚拟字段
|
||||||
|
program: ProgramEntity;
|
||||||
|
|
||||||
page: number = 1;
|
page: number = 1;
|
||||||
size: number = 10;
|
size: number = 10;
|
||||||
|
|
||||||
|
userUnread: any
|
||||||
|
chargeUnread: any
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,28 +58,6 @@ export class ChatGateway implements OnGatewayInit {
|
|||||||
*/
|
*/
|
||||||
@SubscribeMessage('clientMsg')
|
@SubscribeMessage('clientMsg')
|
||||||
async clientMessage(@MessageBody() data: ProgramGroupMessageEntity): Promise<any> {
|
async clientMessage(@MessageBody() data: ProgramGroupMessageEntity): Promise<any> {
|
||||||
|
|
||||||
// 不在线用户
|
|
||||||
let userIds = await this.activeUser(data.groupId)
|
|
||||||
|
|
||||||
if (userIds.length != 0) {
|
|
||||||
// 保存未读消息 redis
|
|
||||||
console.log(userIds)
|
|
||||||
for (let i = 0; i < userIds.length; i++) {
|
|
||||||
let item = userIds[i]
|
|
||||||
// 先取再存
|
|
||||||
let redisData = await this.redisService.getValue(`${data.groupId}_${item}`)
|
|
||||||
if (redisData == null) {
|
|
||||||
this.redisService.setValue(`${data.groupId}_${item}`, JSON.stringify([data]))
|
|
||||||
} else {
|
|
||||||
let arr: any = []
|
|
||||||
arr = JSON.parse(redisData)
|
|
||||||
arr.push(data)
|
|
||||||
this.redisService.setValue(`${data.groupId}_${item}`, JSON.stringify(arr))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存记录
|
// 保存记录
|
||||||
let saveMessage = await this.messageRepository.save(data)
|
let saveMessage = await this.messageRepository.save(data)
|
||||||
|
|
||||||
@@ -89,6 +67,28 @@ export class ChatGateway implements OnGatewayInit {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 不在线用户
|
||||||
|
let userIds = await this.activeUser(data.groupId)
|
||||||
|
|
||||||
|
// 存储未读消息
|
||||||
|
if (userIds.length != 0) {
|
||||||
|
// 保存未读消息 redis
|
||||||
|
console.log(userIds)
|
||||||
|
for (let i = 0; i < userIds.length; i++) {
|
||||||
|
let item = userIds[i]
|
||||||
|
// 先取再存
|
||||||
|
let redisData = await this.redisService.getValue(`${data.groupId}_${item}`)
|
||||||
|
if (redisData == null) {
|
||||||
|
this.redisService.setValue(`${data.groupId}_${item}`, JSON.stringify([saveMessage]))
|
||||||
|
} else {
|
||||||
|
let arr: any = []
|
||||||
|
arr = JSON.parse(redisData)
|
||||||
|
arr.push(saveMessage)
|
||||||
|
this.redisService.setValue(`${data.groupId}_${item}`, JSON.stringify(arr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.server.to(data.groupId.toString()).emit('serverMsg', saveMessage)
|
this.server.to(data.groupId.toString()).emit('serverMsg', saveMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export * from './programGroupService.service';
|
export * from './programGroup.service';
|
||||||
export * from './chat.gateway';
|
export * from './chat.gateway';
|
||||||
export * from './file.service';
|
export * from './file.service';
|
||||||
export * from './redis.service'
|
export * from './redis.service'
|
||||||
|
export * from './message.service'
|
||||||
23
src/service/message.service.ts
Normal file
23
src/service/message.service.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import {Injectable} from "@nestjs/common";
|
||||||
|
import {ReadDto} from "../entity";
|
||||||
|
import {RedisService} from "./redis.service";
|
||||||
|
import {ResultData} from "../const/result";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MessageService {
|
||||||
|
constructor(private readonly redisService: RedisService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取未读消息
|
||||||
|
async getUnread(readDto: ReadDto) {
|
||||||
|
let data = await this.redisService.getValue(`${readDto.groupId}_${readDto.userId}`)
|
||||||
|
data = data == null ? [] : JSON.parse(data)
|
||||||
|
return ResultData.success(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 未读 -> 已读
|
||||||
|
async read(readDto: ReadDto) {
|
||||||
|
this.redisService.delValue(`${readDto.groupId}_${readDto.userId}`)
|
||||||
|
return ResultData.success()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import {Injectable} from '@nestjs/common';
|
import {Injectable} from '@nestjs/common';
|
||||||
import {InjectRepository} from "@nestjs/typeorm";
|
import {InjectRepository} from "@nestjs/typeorm";
|
||||||
import {ProgramEntity, ProgramGroupEntity, UsersEntity} from "../entity";
|
import {ProgramEntity, ProgramGroupEntity, ProgramGroupMessageEntity, UsersEntity} from "../entity";
|
||||||
import {Repository} from "typeorm";
|
import {Repository} from "typeorm";
|
||||||
import {ResultData} from "../const/result";
|
import {ResultData} from "../const/result";
|
||||||
import {isEmptyString} from "../utils/common";
|
import {isEmptyString} from "../utils/common";
|
||||||
|
import {RedisService} from "./redis.service";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ProgramGroupService {
|
export class ProgramGroupService {
|
||||||
@@ -12,6 +13,7 @@ export class ProgramGroupService {
|
|||||||
@InjectRepository(ProgramGroupEntity) private readonly programGroupRepository: Repository<ProgramGroupEntity>,
|
@InjectRepository(ProgramGroupEntity) private readonly programGroupRepository: Repository<ProgramGroupEntity>,
|
||||||
@InjectRepository(ProgramEntity) private readonly programRepository: Repository<ProgramEntity>,
|
@InjectRepository(ProgramEntity) private readonly programRepository: Repository<ProgramEntity>,
|
||||||
@InjectRepository(UsersEntity) private readonly usersRepository: Repository<UsersEntity>,
|
@InjectRepository(UsersEntity) private readonly usersRepository: Repository<UsersEntity>,
|
||||||
|
private readonly redisService: RedisService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,21 +107,45 @@ export class ProgramGroupService {
|
|||||||
"group.user_id = user.id"
|
"group.user_id = user.id"
|
||||||
)
|
)
|
||||||
|
|
||||||
if (programGroup.customerId != null){
|
// 查询最新消息
|
||||||
|
// queryBuilder.leftJoinAndMapOne(
|
||||||
|
// "group.latest_message",
|
||||||
|
// ProgramGroupMessageEntity,
|
||||||
|
// "message",
|
||||||
|
// `
|
||||||
|
// message.group_id = group.group_id and
|
||||||
|
// group.group_id = (
|
||||||
|
// select group_id from program_group_message
|
||||||
|
// where program_group_message.group_id = group.group_id
|
||||||
|
// order by create_time desc
|
||||||
|
// limit 1
|
||||||
|
// )
|
||||||
|
// `)
|
||||||
|
queryBuilder.addSelect(subQuery => {
|
||||||
|
return subQuery
|
||||||
|
.select("max(message.create_time)")
|
||||||
|
.from(ProgramGroupMessageEntity, "message")
|
||||||
|
.where("message.group_id = group.group_id");
|
||||||
|
}, "latest_message_time")
|
||||||
|
|
||||||
|
if (programGroup.customerId != null) {
|
||||||
queryBuilder.andWhere("group.customer_id = :customerId", {customerId: programGroup.customerId})
|
queryBuilder.andWhere("group.customer_id = :customerId", {customerId: programGroup.customerId})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (programGroup.userId != null){
|
if (programGroup.userId != null) {
|
||||||
queryBuilder.orWhere("group.user_id = :userId", {userId: programGroup.userId})
|
queryBuilder.orWhere("group.user_id = :userId", {userId: programGroup.userId})
|
||||||
queryBuilder.orWhere("group.charge_id = :charge_id", {charge_id: programGroup.userId})
|
queryBuilder.orWhere("group.charge_id = :charge_id", {charge_id: programGroup.userId})
|
||||||
}
|
}
|
||||||
|
|
||||||
queryBuilder
|
queryBuilder
|
||||||
.orderBy('program.id', 'DESC')
|
.orderBy("latest_message_time", 'DESC')
|
||||||
.take(programGroup.size || 10)
|
.take(programGroup.size || 10)
|
||||||
.skip(offset || 0);
|
.skip(offset || 0);
|
||||||
|
|
||||||
const [items, total] = await queryBuilder.getManyAndCount();
|
let [items, total] = await queryBuilder.getManyAndCount();
|
||||||
|
|
||||||
|
// 将未读数据(redis)塞入数据(list)中
|
||||||
|
items = await this.searchUnRead(items)
|
||||||
|
|
||||||
let data = {
|
let data = {
|
||||||
list: items,
|
list: items,
|
||||||
@@ -147,4 +173,17 @@ export class ProgramGroupService {
|
|||||||
return ResultData.fail(500, err);
|
return ResultData.fail(500, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理未读消息
|
||||||
|
// 返回用户和项目负责人的未读消息
|
||||||
|
async searchUnRead(list: ProgramGroupEntity[]) {
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
let item = list[i];
|
||||||
|
let userUnreadValue = await this.redisService.getValue(`${item.groupId}_${item.userId}`)
|
||||||
|
let chargeUnreadValue = await this.redisService.getValue(`${item.groupId}_${item.chargeId}`)
|
||||||
|
item.userUnread = userUnreadValue == null ? [] : JSON.parse(userUnreadValue)
|
||||||
|
item.chargeUnread = chargeUnreadValue == null ? [] : JSON.parse(chargeUnreadValue)
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -22,4 +22,8 @@ export class RedisService {
|
|||||||
getValue(key: string) {
|
getValue(key: string) {
|
||||||
return this.redisClient.get(key);
|
return this.redisClient.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delValue(key: string) {
|
||||||
|
return this.redisClient.del(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user