2025-09-30

未读变已读
查询列表排序
This commit is contained in:
2025-09-30 16:41:10 +08:00
parent 51052e59a2
commit 541d7842ce
11 changed files with 153 additions and 53 deletions

View File

@@ -1,2 +1,3 @@
export * from './programGroup.controller';
export * from './file.controller';
export * from './file.controller';
export * from './message.controller'

View 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)
}
}

View File

@@ -26,5 +26,4 @@ export class ProgramGroupController {
async getOne(@Param() programGroup: ProgramGroupEntity) {
return await this.programGroupService.getOne(programGroup);
}
}

View File

@@ -0,0 +1,4 @@
export class ReadDto {
groupId: number;
userId: number;
}

View File

@@ -1,4 +1,6 @@
export * from './program.entity';
export * from './users.entity';
export * from './programGroup.entity';
export * from './programGroupMessage.entity';
export * from './programGroupMessage.entity';
export * from './dto/read.dto'

View File

@@ -1,32 +1,36 @@
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
import {Column, Entity, PrimaryGeneratedColumn} from "typeorm";
import {ProgramEntity} from "./program.entity";
@Entity("program_group", { schema: "test" })
@Entity("program_group", {schema: "test"})
export class ProgramGroupEntity {
@PrimaryGeneratedColumn({ type: "int", name: "group_id", comment: "群组ID" })
groupId: number;
@PrimaryGeneratedColumn({type: "int", name: "group_id", comment: "群组ID"})
groupId: number;
@Column("int", { name: "program_id", comment: "项目ID" })
programId: number;
@Column("int", {name: "program_id", comment: "项目ID"})
programId: number;
@Column("int", { name: "charge_id", comment: "负责人ID" })
chargeId: number;
@Column("int", {name: "charge_id", comment: "负责人ID"})
chargeId: number;
@Column("int", { name: "customer_id", comment: "客服ID" })
customerId: number;
@Column("int", {name: "customer_id", comment: "客服ID"})
customerId: number;
@Column("int", { name: "user_id", comment: "用户ID" })
userId: number;
@Column("int", {name: "user_id", comment: "用户ID"})
userId: number;
@Column("datetime", {
name: "create_time",
comment: "创建时间",
default: () => "CURRENT_TIMESTAMP",
})
createTime: Date;
@Column("datetime", {
name: "create_time",
comment: "创建时间",
default: () => "CURRENT_TIMESTAMP",
})
createTime: Date;
program: ProgramEntity;
// 虚拟字段
program: ProgramEntity;
page: number = 1;
size: number = 10;
page: number = 1;
size: number = 10;
userUnread: any
chargeUnread: any
}

View File

@@ -58,28 +58,6 @@ export class ChatGateway implements OnGatewayInit {
*/
@SubscribeMessage('clientMsg')
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)
@@ -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)
}

View File

@@ -1,4 +1,5 @@
export * from './programGroupService.service';
export * from './programGroup.service';
export * from './chat.gateway';
export * from './file.service';
export * from './redis.service'
export * from './redis.service'
export * from './message.service'

View 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()
}
}

View File

@@ -1,9 +1,10 @@
import {Injectable} from '@nestjs/common';
import {InjectRepository} from "@nestjs/typeorm";
import {ProgramEntity, ProgramGroupEntity, UsersEntity} from "../entity";
import {ProgramEntity, ProgramGroupEntity, ProgramGroupMessageEntity, UsersEntity} from "../entity";
import {Repository} from "typeorm";
import {ResultData} from "../const/result";
import {isEmptyString} from "../utils/common";
import {RedisService} from "./redis.service";
@Injectable()
export class ProgramGroupService {
@@ -12,6 +13,7 @@ export class ProgramGroupService {
@InjectRepository(ProgramGroupEntity) private readonly programGroupRepository: Repository<ProgramGroupEntity>,
@InjectRepository(ProgramEntity) private readonly programRepository: Repository<ProgramEntity>,
@InjectRepository(UsersEntity) private readonly usersRepository: Repository<UsersEntity>,
private readonly redisService: RedisService,
) {
}
@@ -105,21 +107,45 @@ export class ProgramGroupService {
"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})
}
if (programGroup.userId != null){
if (programGroup.userId != null) {
queryBuilder.orWhere("group.user_id = :userId", {userId: programGroup.userId})
queryBuilder.orWhere("group.charge_id = :charge_id", {charge_id: programGroup.userId})
}
queryBuilder
.orderBy('program.id', 'DESC')
.orderBy("latest_message_time", 'DESC')
.take(programGroup.size || 10)
.skip(offset || 0);
const [items, total] = await queryBuilder.getManyAndCount();
let [items, total] = await queryBuilder.getManyAndCount();
// 将未读数据(redis)塞入数据(list)中
items = await this.searchUnRead(items)
let data = {
list: items,
@@ -147,4 +173,17 @@ export class ProgramGroupService {
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
}
}

View File

@@ -22,4 +22,8 @@ export class RedisService {
getValue(key: string) {
return this.redisClient.get(key);
}
delValue(key: string) {
return this.redisClient.del(key);
}
}