2025-09-28 09:30:27 +08:00
|
|
|
import {Injectable} from '@nestjs/common';
|
|
|
|
|
import {InjectRepository} from "@nestjs/typeorm";
|
2025-09-30 16:41:10 +08:00
|
|
|
import {ProgramEntity, ProgramGroupEntity, ProgramGroupMessageEntity, UsersEntity} from "../entity";
|
2025-09-28 09:30:27 +08:00
|
|
|
import {Repository} from "typeorm";
|
|
|
|
|
import {ResultData} from "../const/result";
|
|
|
|
|
import {isEmptyString} from "../utils/common";
|
2025-09-30 16:41:10 +08:00
|
|
|
import {RedisService} from "./redis.service";
|
2025-09-28 09:30:27 +08:00
|
|
|
|
|
|
|
|
@Injectable()
|
|
|
|
|
export class ProgramGroupService {
|
|
|
|
|
|
|
|
|
|
constructor(
|
|
|
|
|
@InjectRepository(ProgramGroupEntity) private readonly programGroupRepository: Repository<ProgramGroupEntity>,
|
|
|
|
|
@InjectRepository(ProgramEntity) private readonly programRepository: Repository<ProgramEntity>,
|
|
|
|
|
@InjectRepository(UsersEntity) private readonly usersRepository: Repository<UsersEntity>,
|
2025-09-30 16:41:10 +08:00
|
|
|
private readonly redisService: RedisService,
|
2025-09-28 09:30:27 +08:00
|
|
|
) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async add(programGroup: ProgramGroupEntity) {
|
|
|
|
|
try {
|
|
|
|
|
// 前置判断
|
|
|
|
|
// 判断是否为空
|
|
|
|
|
if (isEmptyString(programGroup.programId) || isEmptyString(programGroup.userId)) {
|
|
|
|
|
return ResultData.fail(500, "参数不能为空")
|
|
|
|
|
}
|
|
|
|
|
// 查找program信息
|
|
|
|
|
let program = await this.programRepository.findOne({
|
|
|
|
|
where: {
|
|
|
|
|
id: programGroup.programId
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
if (program == null) {
|
|
|
|
|
return ResultData.fail(500, "未找到项目信息")
|
|
|
|
|
}
|
|
|
|
|
// 用户是否有权限发起群组(本人不行,系统用户不行,创建过同样会话不行)
|
|
|
|
|
if (programGroup.userId == program.linkmanId) {
|
|
|
|
|
return ResultData.fail(500, "不能创建自己的项目群组")
|
|
|
|
|
}
|
|
|
|
|
let user = await this.usersRepository.findOne({
|
|
|
|
|
where: {
|
|
|
|
|
id: programGroup.userId
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
if (user?.isSystemAccount) {
|
|
|
|
|
return ResultData.fail(500, "系统用户不能创建群组")
|
|
|
|
|
}
|
|
|
|
|
let groups = await this.programGroupRepository.find({
|
|
|
|
|
where: {
|
|
|
|
|
programId: programGroup.programId,
|
|
|
|
|
userId: programGroup.userId
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
if (groups.length > 0) {
|
|
|
|
|
return ResultData.fail(500, "已经创建过群组")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 匹配客服
|
|
|
|
|
let customers = await this.usersRepository.findBy({userType: "customer"});
|
|
|
|
|
if (customers.length == 0) {
|
|
|
|
|
return ResultData.fail(500, "没有客服人员")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let customerList = await this.usersRepository.createQueryBuilder("users")
|
|
|
|
|
.leftJoinAndMapMany("users.groups", "program_group", "group", "users.id = group.customer_id")
|
|
|
|
|
.where("users.user_type = :type", {type: "customer"})
|
|
|
|
|
.getMany()
|
|
|
|
|
|
|
|
|
|
// 客服分配任务量
|
|
|
|
|
var index = 0 // 任务最小值
|
|
|
|
|
for (let i = 0; i < customerList.length - 1; i++) {
|
|
|
|
|
if (customerList[i].groups.length > customerList[i + 1].groups.length) {
|
|
|
|
|
index = i + 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
programGroup.customerId = customerList[index].id
|
|
|
|
|
|
|
|
|
|
// 创建聊天
|
|
|
|
|
programGroup.chargeId = program.linkmanId
|
|
|
|
|
|
|
|
|
|
let result = await this.programGroupRepository.save(programGroup)
|
2025-09-28 17:28:52 +08:00
|
|
|
return result != null ? ResultData.success(result) : ResultData.fail(500, "创建群组失败");
|
2025-09-28 09:30:27 +08:00
|
|
|
} catch (err) {
|
|
|
|
|
return ResultData.fail(500, err);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async getList(programGroup: ProgramGroupEntity) {
|
|
|
|
|
try {
|
|
|
|
|
programGroup.page = programGroup.page || 1;
|
|
|
|
|
programGroup.size = programGroup.size || 10;
|
|
|
|
|
const offset = (programGroup.page - 1) * programGroup.size;
|
|
|
|
|
|
|
|
|
|
const queryBuilder = this.programGroupRepository.createQueryBuilder("group")
|
|
|
|
|
queryBuilder.leftJoinAndMapOne(
|
|
|
|
|
"group.program",
|
|
|
|
|
ProgramEntity,
|
|
|
|
|
"program",
|
|
|
|
|
"group.program_id = program.id"
|
|
|
|
|
)
|
2025-10-13 17:30:24 +08:00
|
|
|
|
|
|
|
|
queryBuilder.leftJoinAndMapOne(
|
|
|
|
|
"group.chargeUser",
|
|
|
|
|
UsersEntity,
|
|
|
|
|
"chargeUser",
|
|
|
|
|
"group.charge_id = chargeUser.id"
|
|
|
|
|
)
|
|
|
|
|
|
2025-09-30 13:41:41 +08:00
|
|
|
queryBuilder.leftJoinAndMapOne(
|
|
|
|
|
"group.user",
|
|
|
|
|
UsersEntity,
|
|
|
|
|
"user",
|
|
|
|
|
"group.user_id = user.id"
|
|
|
|
|
)
|
2025-09-28 09:30:27 +08:00
|
|
|
|
2025-09-30 16:41:10 +08:00
|
|
|
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) {
|
2025-09-28 17:28:52 +08:00
|
|
|
queryBuilder.andWhere("group.customer_id = :customerId", {customerId: programGroup.customerId})
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-30 16:41:10 +08:00
|
|
|
if (programGroup.userId != null) {
|
2025-09-28 17:28:52 +08:00
|
|
|
queryBuilder.orWhere("group.user_id = :userId", {userId: programGroup.userId})
|
|
|
|
|
queryBuilder.orWhere("group.charge_id = :charge_id", {charge_id: programGroup.userId})
|
|
|
|
|
}
|
2025-09-28 09:30:27 +08:00
|
|
|
|
2025-10-13 17:30:24 +08:00
|
|
|
if (programGroup.keyword != null){
|
|
|
|
|
queryBuilder.andWhere(
|
|
|
|
|
"(program.name LIKE :nameKeyword OR program.company LIKE :companyKeyword)",
|
|
|
|
|
{
|
|
|
|
|
nameKeyword: '%' + programGroup.keyword + '%',
|
|
|
|
|
companyKeyword: '%' + programGroup.keyword + '%'
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-28 09:30:27 +08:00
|
|
|
queryBuilder
|
2025-09-30 16:41:10 +08:00
|
|
|
.orderBy("latest_message_time", 'DESC')
|
2025-09-28 09:30:27 +08:00
|
|
|
.take(programGroup.size || 10)
|
|
|
|
|
.skip(offset || 0);
|
|
|
|
|
|
2025-10-13 17:30:24 +08:00
|
|
|
// console.log(queryBuilder.getSql())
|
|
|
|
|
|
2025-09-30 16:41:10 +08:00
|
|
|
let [items, total] = await queryBuilder.getManyAndCount();
|
|
|
|
|
|
|
|
|
|
// 将未读数据(redis)塞入数据(list)中
|
|
|
|
|
items = await this.searchUnRead(items)
|
2025-09-28 09:30:27 +08:00
|
|
|
|
|
|
|
|
let data = {
|
|
|
|
|
list: items,
|
|
|
|
|
total,
|
|
|
|
|
page: programGroup.page || 1,
|
|
|
|
|
size: programGroup.size || 10,
|
|
|
|
|
pages: Math.ceil(total / (programGroup.size || 10))
|
|
|
|
|
}
|
|
|
|
|
return ResultData.success(data);
|
|
|
|
|
} catch (err) {
|
|
|
|
|
return ResultData.fail(500, err);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-28 17:28:52 +08:00
|
|
|
|
|
|
|
|
async getOne(programGroup: ProgramGroupEntity) {
|
|
|
|
|
try {
|
|
|
|
|
let result = await this.programGroupRepository.findOne({
|
|
|
|
|
where: {
|
|
|
|
|
programId: programGroup.programId,
|
|
|
|
|
userId: programGroup.userId
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
return result != null ? ResultData.success(result) : ResultData.fail(500, "未找到群组信息");
|
|
|
|
|
} catch (err) {
|
|
|
|
|
return ResultData.fail(500, err);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-30 16:41:10 +08:00
|
|
|
|
|
|
|
|
// 处理未读消息
|
|
|
|
|
// 返回用户和项目负责人的未读消息
|
|
|
|
|
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}`)
|
2025-10-13 17:30:24 +08:00
|
|
|
let customerUnreadValue = await this.redisService.getValue(`${item.groupId}_${item.customerId}`)
|
2025-09-30 16:41:10 +08:00
|
|
|
item.userUnread = userUnreadValue == null ? [] : JSON.parse(userUnreadValue)
|
|
|
|
|
item.chargeUnread = chargeUnreadValue == null ? [] : JSON.parse(chargeUnreadValue)
|
2025-10-13 17:30:24 +08:00
|
|
|
item.customerUnread = customerUnreadValue == null ? [] : JSON.parse(customerUnreadValue)
|
2025-09-30 16:41:10 +08:00
|
|
|
}
|
|
|
|
|
return list
|
|
|
|
|
}
|
2025-10-09 15:15:09 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
async getGroup(groupId: number) {
|
|
|
|
|
try {
|
|
|
|
|
let result = await this.programGroupRepository.findOne({
|
|
|
|
|
where: {
|
|
|
|
|
groupId
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
if (result != null){
|
|
|
|
|
result.program = await this.programRepository.createQueryBuilder("program")
|
|
|
|
|
.leftJoinAndMapOne(
|
|
|
|
|
"program.linkman",
|
|
|
|
|
UsersEntity,
|
|
|
|
|
"linkman",
|
|
|
|
|
"program.linkman_id = linkman.id"
|
|
|
|
|
).where("program.id = :id", {id: result.programId})
|
|
|
|
|
.getOne()
|
|
|
|
|
return ResultData.success(result)
|
|
|
|
|
}else {
|
|
|
|
|
throw "未找到群组信息"
|
|
|
|
|
}
|
|
|
|
|
} catch (err) {
|
|
|
|
|
return ResultData.fail(500, err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2025-09-28 09:30:27 +08:00
|
|
|
}
|