908 lines
24 KiB
JavaScript
Raw Normal View History

2026-07-27 11:28:33 +08:00
let dayjs = require("dayjs");
let utils = require("../utils.js");
const api = require("../../api");
let db = null;
exports.main = async (content, DB) => {
db = DB;
switch (content.type) {
case "getCustomerStatistics":
return await exports.getCustomerStatistics(content);
case "getServiceAndmemberTotalByTeamId":
return await exports.getServiceAndmemberTotalByTeamId(content);
case "getServiceAndmemberTotalByUserId":
return await exports.getServiceAndmemberTotalByUserId(content);
case "getServiceTrendByTeamId":
return await exports.getServiceTrendByTeamId(content);
case "getMemberTrendByTeamId":
return await exports.getMemberTrendByTeamId(content);
case "getUsersMemberByTeamId":
return await exports.getUsersMemberByTeamId(content);
case "getTeamsServiceAndMemberCount":
return await getTeamsServiceAndMemberCount(content);
case "getStaffServiceAndMemberCount":
return await getStaffServiceAndMemberCount(content);
case "getCustomerSourceCountSort":
return await getCustomerSourceCountSort(content);
case "getCustomerGroupCountSort":
return await getCustomerGroupCountSort(content);
case "getCusomterAndServiceCount":
return await getCusomterAndServiceCount(content);
case "getStaffRate":
return await getStaffRate(content);
case "getScoreRateTrend":
return await getScoreRateTrend(content);
case "getTeamCustmerCount":
return await getTeamCustmerCount(content);
}
};
// 获取客户数和服务数
async function getCusomterAndServiceCount(content) {
const { corpId } = content;
const todayStartTime = dayjs().startOf("day").valueOf();
const todayEndTime = dayjs().endOf("day").valueOf();
// 获取客户总数
const customerTotalCount = await db
.collection("member")
.find({ corpId })
.count();
const serviceTotalCount = await db
.collection("service-record")
.find({ corpId, eventType: { $ne: "serviceRate" } })
.count();
let todayCustomerCount = await db
.collection("member")
.find({
corpId,
createTime: { $gte: todayStartTime, $lt: todayEndTime },
})
.count();
let todayServiceCount = await db
.collection("service-record")
.find({
corpId,
eventType: { $ne: "serviceRate" },
createTime: { $gte: todayStartTime, $lt: todayEndTime },
})
.count();
return {
success: true,
message: "获取成功",
customerTotalCount,
serviceTotalCount,
todayCustomerCount,
todayServiceCount,
};
}
// 分组客户数据统计
async function getCustomerGroupCountSort(content) {
const { corpId } = content;
const data = await db
.collection("member")
.aggregate([
{ $match: { corpId } },
{ $group: { _id: "$groupIds", count: { $sum: 1 } } },
])
.toArray();
const result = data.reduce((acc, item) => {
if (Array.isArray(item._id)) {
item._id.forEach((id) => {
acc[id] = (acc[id] || 0) + item.count;
});
} else if (item._id) {
acc[item._id] = (acc[item._id] || 0) + item.count;
}
return acc;
}, {});
let list = Object.entries(result).map(([groupId, count]) => ({
groupId,
count,
}));
const ids = list.map((item) => item.groupId);
let res = await db
.collection("group")
.find({ _id: { $in: ids } })
.limit(1000)
.toArray();
list = list.map((item) => {
let group = res.find((i) => i._id === item.groupId);
if (!group) {
return {
...item,
groupName: "未知",
};
} else {
return {
...item,
groupName: group.groupName,
parentGroupId: group.parentGroupId,
};
}
});
list = list.filter((i) => i.groupName !== "未知");
let mergedList = [];
list.forEach((item) => {
if (!item.parentGroupId) {
mergedList.push(item);
return;
}
let existingItem = mergedList.find(
(el) => el.parentGroupId === item.parentGroupId
);
if (existingItem) {
existingItem.count += item.count;
} else {
mergedList.push(item);
}
});
mergedList.sort((a, b) => b.count - a.count);
let countAfterFive = 0;
if (mergedList.length > 5) {
for (let i = 5; i < mergedList.length; i++) {
countAfterFive += mergedList[i].count;
}
mergedList = mergedList.slice(0, 5);
mergedList.push({
groupName: "其他",
count: countAfterFive,
});
}
return {
success: true,
message: "获取成功",
list: mergedList,
};
}
// 获取获取客户来源的客户数据
async function getCustomerSourceCountSort(content) {
const { corpId, sources = [] } = content;
const PAGE_SIZE = 1000; // 每页查询的记录数,可以根据实际情况调整
let page = 0;
let hasMoreData = true;
let allData = [];
while (hasMoreData) {
const data = await db
.collection("member")
.aggregate([
{ $match: { corpId } },
{ $skip: page * PAGE_SIZE },
{ $limit: PAGE_SIZE },
{ $group: { _id: "$customerSource", count: { $sum: 1 } } },
])
.toArray();
if (data.length > 0) {
allData = allData.concat(data);
page++;
} else {
hasMoreData = false; // 如果没有更多数据,停止查询
}
}
// 处理数据
const result = allData.reduce((acc, item) => {
if (Array.isArray(item._id)) {
item._id.forEach((id) => {
acc[id] = (acc[id] || 0) + item.count;
});
} else if (item._id) {
acc[item._id] = (acc[item._id] || 0) + item.count;
}
return acc;
}, {});
// 获取未知来源的数据
let unknowSourceCount = allData.find((i) => !i._id)
? allData.find((i) => !i._id).count
: 0;
let list = Object.entries(result)
.map(([sourceName, count]) => ({
sourceName,
count,
}))
.filter((i) => sources.some((item) => item === i.sourceName));
list.sort((a, b) => b.count - a.count);
if (list.length > 5) {
// 5名之后相加
let countAfterFive = 0;
for (let i = 5; i < list.length; i++) {
countAfterFive += list[i].count;
}
list = list.slice(0, 5);
list.push({
sourceName: "其他",
count: countAfterFive,
});
}
list.push({
sourceName: "未知",
count: unknowSourceCount,
});
return {
success: true,
message: "获取成功",
data: allData,
list,
};
}
//获取团队服务和客户总数
async function getTeamsServiceAndMemberCount(context) {
try {
const { corpId, dates } = context;
let teamList = await getCorpTeams(corpId);
teamList = teamList.map((item) => {
return {
...item,
corpId,
dates,
};
});
const handler = async (item) => {
let { data } = await exports.getServiceAndmemberTotalByTeamId(item);
let { averageScore } = await getStaffRate(item);
return {
...data,
satisfaction: averageScore,
};
};
let list = await utils.processInBatches(teamList, handler, 10);
return {
success: true,
message: "获取成功",
list,
};
} catch (e) {
return { success: false, message: e.message };
}
}
// 获取满意度评分趋势
async function getScoreRateTrend(context) {
const { corpId, dates } = context;
const { startTime, lastTime } = getStartAndEndTime(dates);
let params = {
corpId,
};
if (dates && Array.isArray(dates) && dates.length !== 0) {
params["createTime"] = { $gte: startTime, $lte: lastTime };
}
// 已评价的总数
let ratedTotalCount = await db
.collection("corp-rate-records")
.find({ ...params, rate: { $exists: true } })
.count();
// 未评价的总数
let unratedTotalCount = await db
.collection("corp-rate-records")
.find({
...params,
rate: { $exists: false },
expireTime: { $lte: new Date().getTime() },
})
.count();
const getRateCount = async (rate) => {
return await db
.collection("corp-rate-records")
.find({ ...params, rate })
.count();
};
let arrCount = Promise.all([
getRateCount(5),
getRateCount(4),
getRateCount(3),
getRateCount(2),
getRateCount(1),
]);
let [
fiveStarCount,
fourStarCount,
threeStarCount,
twoStarCount,
oneStareCount,
] = await arrCount;
return {
success: true,
message: "获取成功",
count: {
total: ratedTotalCount + unratedTotalCount,
fiveStarCount: fiveStarCount + unratedTotalCount,
fourStarCount,
threeStarCount,
twoStarCount,
oneStareCount,
},
};
}
// 获取员工服务满意度评分
async function getStaffRate(context) {
const { corpId, dates, userId, teamId } = context;
const { startTime, lastTime } = getStartAndEndTime(dates);
const rateQuery = { corpId, teamId };
if (userId) rateQuery.userId = userId;
if (dates && Array.isArray(dates) && dates.length !== 0) {
rateQuery["createTime"] = { $gte: startTime, $lte: lastTime };
}
// 获取 4 5星评价的条数
const goodRateCout = await api.getKnowledgeBaseApi({
type: "getRateRecordCount",
params: { ...rateQuery, rate: { $in: [4, 5] } },
corpId,
});
// 获取 1 2 3星评价的条数
const notGoodRateCout = await api.getKnowledgeBaseApi({
type: "getRateRecordCount",
params: { ...rateQuery, rate: { $in: [1, 2, 3] } },
corpId,
});
// 获取超时未评价的条数 (超时未评价默认好评)
const unratedCount = await api.getKnowledgeBaseApi({
type: "getRateRecordCount",
params: {
...rateQuery,
rate: { $exists: false },
expireTime: { $lte: new Date().getTime() },
},
corpId,
});
const rate =
(goodRateCout + unratedCount) /
Math.max(goodRateCout + notGoodRateCout + unratedCount, 1);
const percent = (rate * 100).toFixed(2);
return {
success: true,
message: "获取成功",
averageScore: percent,
};
}
async function getStaffServiceAndMemberCount(context) {
const { corpId, dates } = context;
let staffList = await getCorpStaffs(corpId);
staffList = staffList.map((item) => {
return {
userId: item.userid,
corpId,
dates,
};
});
const handler = async (item) => {
let { data } = await exports.getServiceAndmemberTotalByUserId(item);
let { averageScore } = await getStaffRate(item);
return {
...data,
satisfaction: averageScore,
};
};
let list = await utils.processInBatches(staffList, handler, 10);
return {
success: true,
message: "获取成功",
list,
};
}
exports.getServiceAndmemberTotalByTeamId = async (context) => {
const { corpId, teamId, dates, name } = context;
const { startTime, lastTime } = getStartAndEndTime(dates);
let memberParmas = {
corpId,
teamId,
};
let serviceParams = {
corpId,
executeTeamId: teamId,
eventType: { $ne: "serviceRate" },
};
let registrationParams = {
teamId,
};
if (Array.isArray(dates) && dates.length !== 0) {
memberParmas["createTime"] = { $gte: startTime, $lte: lastTime };
serviceParams["executionTime"] = { $gte: startTime, $lte: lastTime };
registrationParams["createTime"] = { $gte: startTime, $lte: lastTime };
}
try {
let memberCount = await db.collection("member").find(memberParmas).count();
let serviceCount = await db
.collection("service-record")
.find(serviceParams)
.count();
let visitCount = await db
.collection("registration")
.find(registrationParams)
.count();
return {
success: true,
message: "获取成功",
data: {
memberCount,
serviceCount,
visitCount,
teamName: name,
},
};
} catch {
return {
success: false,
message: "获取失败",
};
}
};
exports.getServiceAndmemberTotalByUserId = async (context) => {
const { corpId, userId, dates } = context;
const { startTime, lastTime } = getStartAndEndTime(dates);
try {
let memberParams = {
corpId,
personResponsibles: { $elemMatch: { corpUserId: userId } },
};
let serviceParams = {
corpId,
executorUserId: userId,
eventType: { $ne: "serviceRate" },
};
if (Array.isArray(dates) && dates.length !== 0) {
memberParams["createTime"] = { $gte: startTime, $lte: lastTime };
serviceParams["executionTime"] = { $gte: startTime, $lte: lastTime };
}
let memberCount = await db.collection("member").find(memberParams).count();
let serviceCount = await db
.collection("service-record")
.find(serviceParams)
.count();
let res = await db
.collection("member")
.find(memberParams)
.project({
name: 1,
_id: 1,
personResponsibles: 1,
})
.toArray();
return {
success: true,
message: "获取成功",
data: {
memberCount,
serviceCount,
userId,
res,
},
};
} catch {
return {
success: false,
message: "获取失败",
};
}
};
// 获取所有团队
async function getCorpTeams(corpId) {
const fetchData = async (page, pageSize, db) => {
const { list = [] } = await api.getCorpApi({
type: "getCorpTeams",
corpId,
pageSize,
page,
fields: { name: 1, teamId: 1 },
showCustomerCount: false,
});
return Array.isArray(list) ? list : [];
};
const list = await utils.getAllData(fetchData, db);
return list;
}
// 获取所有成员
async function getCorpStaffs(corpId) {
const fetchData = async (page, pageSize, db) => {
const { data } = await api.getCorpApi({
type: 'getCorpMember',
page,
pageSize,
params: { corpId, open_userid: { $exists: true } }
})
const list = Array.isArray(data) ? data.map(i => ({ userid: i.userid })).filter(i => i.userid) : [];
return list;
};
const list = await utils.getAllData(fetchData, db);
return list;
}
exports.getCustomerStatistics = async (content) => {
const { corpId } = content;
// 校验 corpId 是否存在
if (!corpId) {
return {
success: false,
message: "机构id不能为空",
};
}
try {
// 获取今日的起始和结束时间戳
const todayStartTime = dayjs().startOf("day").valueOf();
const todayEndTime = dayjs().endOf("day").valueOf();
// 使用聚合管道来进行多个统计查询
const result = await db
.collection("member")
.aggregate([
{
$match: { corpId },
},
{
$facet: {
// 获取客户总数
totalCount: [{ $count: "total" }],
// 获取已加好友数
friendCount: [
{ $match: { externalUserId: { $ne: "", $exists: true } } },
{ $count: "total" },
],
// 获取未加好友数
noFriendCount: [
{
$match: {
$or: [
{ externalUserId: { $eq: "" } },
{ externalUserId: { $exists: false } },
],
},
},
{ $count: "total" },
],
// 获取今日新增客户数
todayAddCustomerCount: [
{
$match: {
createTime: { $gte: todayStartTime, $lt: todayEndTime },
},
},
{ $count: "total" },
],
// 获取今日新增好友数
todayAddFriendCount: [
{
$match: {
externalUserId: { $ne: "", $exists: true },
createTime: { $gte: todayStartTime, $lt: todayEndTime },
},
},
{ $count: "total" },
],
// 获取今日未加好友数
todayNoFriendCount: [
{
$match: {
$or: [
{ externalUserId: { $eq: "" } },
{ externalUserId: { $exists: false } },
],
createTime: { $gte: todayStartTime, $lt: todayEndTime },
},
},
{ $count: "total" },
],
},
},
{
$project: {
customerTotalCount: { $arrayElemAt: ["$totalCount.total", 0] },
friendCount: { $arrayElemAt: ["$friendCount.total", 0] },
noFriendCount: { $arrayElemAt: ["$noFriendCount.total", 0] },
todayAddCustomerCount: {
$arrayElemAt: ["$todayAddCustomerCount.total", 0],
},
todayAddFriendCount: {
$arrayElemAt: ["$todayAddFriendCount.total", 0],
},
todayNoFriendCount: {
$arrayElemAt: ["$todayNoFriendCount.total", 0],
},
},
},
])
.toArray();
// 处理返回的数据,将缺失的字段赋值为 0
const stats = result[0] || {};
return {
success: true,
message: "获取成功",
data: {
customerTotalCount: stats.customerTotalCount || 0,
friendCount: stats.friendCount || 0,
noFriendCount: stats.noFriendCount || 0,
todayAddCustomerCount: stats.todayAddCustomerCount || 0,
todayAddFriendCount: stats.todayAddFriendCount || 0,
todayNoFriendCount: stats.todayNoFriendCount || 0,
},
};
} catch (error) {
return {
success: false,
message: "获取失败",
};
}
};
function getStartAndEndTime(dates) {
if (!dates || dates.length === 0) {
return {
startTime: "",
lastTime: "",
};
}
let t_1 = dates[0];
let t_2 = dates[1];
return {
startTime: t_1 && new Date(t_1).setHours(0, 0, 0, 0),
lastTime: t_2 && new Date(t_2).setHours(23, 59, 59, 999),
};
}
exports.getMemberTrendByTeamId = async (context) => {
const { corpId, teamId, dates, userId, dataType = "increaseCount" } = context;
const { startTime, lastTime } = getStartAndEndTime(dates);
let params = {
createTime: { $gte: startTime, $lte: lastTime },
};
try {
let result = {};
if (dataType === "increaseCount") {
if (userId) {
params["personResponsibles"] = {
$elemMatch: { corpUserId: userId, teamId: teamId },
};
}
params["corpId"] = corpId;
params["teamId"] = teamId;
result = await db
.collection("member")
.aggregate([
{ $match: params },
{
$group: {
_id: {
$dateToString: {
format: "%Y-%m-%d",
date: { $toDate: "$createTime" },
},
},
count: { $sum: 1 },
},
},
])
.toArray();
} else if (dataType === "visitCount") {
params["teamId"] = teamId;
result = await db
.collection("registration")
.aggregate([
{ $match: params },
{
$group: {
_id: {
$dateToString: {
format: "%Y-%m-%d",
date: { $toDate: "$createTime" },
},
},
count: { $sum: 1 },
},
},
])
.toArray();
} else if (dataType === "peopleCount") {
params["corpId"] = corpId;
params["executeTeamId"] = teamId;
if (userId) params["creatorUserId"] = userId;
result = await db
.collection("service-record")
.aggregate([
{ $match: params },
{
$group: {
_id: {
$dateToString: {
format: "%Y-%m-%d",
date: { $toDate: "$createTime" },
},
},
count: { $sum: 1 },
},
},
])
.toArray();
}
let list = result;
let filledArray = fillDateGaps(list, dates[0], dates[1]);
return {
success: true,
message: "获取成功",
data: filledArray,
};
} catch (error) {
return {
success: false,
message: "获取失败",
};
}
};
exports.getServiceTrendByTeamId = async (context) => {
const { corpId, teamId, userId, dates } = context;
const { startTime, lastTime } = getStartAndEndTime(dates);
let params = {
corpId,
executeTeamId: teamId,
createTime: { $gte: startTime, $lte: lastTime },
};
if (userId) {
params["executorUserId"] = userId;
}
try {
const result = await db
.collection("service-record")
.aggregate([
{ $match: params },
{
$group: {
_id: {
$dateToString: {
format: "%Y-%m-%d",
date: { $toDate: "$createTime" },
},
},
count: { $sum: 1 },
},
},
])
.toArray();
let list = result;
let filledArray = fillDateGaps(list, dates[0], dates[1]);
return {
success: true,
message: "获取成功",
data: filledArray,
params,
};
} catch (error) {
return {
success: false,
message: "获取失败",
};
}
};
// 获取团队成员客户数
exports.getUsersMemberByTeamId = async (context) => {
try {
const { memberList } = context;
let counts = [];
let arr = memberList.map((i) => {
return getServiceAndMemberCount(context, i);
});
for (let i = 0; i < arr.length; i += 10) {
const promiseArr = arr.slice(i, i + 10);
const list = await Promise.all(promiseArr);
counts = counts.concat(list);
}
return {
success: true,
message: "获取成功",
data: counts,
};
} catch (error) {
return {
success: false,
message: "获取失败",
};
}
};
async function getServiceAndMemberCount(context, userId) {
const { corpId, teamId, dates } = context;
const { startTime, lastTime } = getStartAndEndTime(dates);
const query = {
teamId,
personResponsibles: { $elemMatch: { corpUserId: userId, teamId } },
createTime: { $gte: startTime, $lte: lastTime },
};
let servicQuery = {
corpId,
createTime: { $gte: startTime, $lte: lastTime },
executorUserId: userId,
executeTeamId: teamId,
eventType: { $ne: "serviceRate" },
};
const customerCount = await db
.collection("member")
.find({ ...query, corpId })
.count();
const visitCount = await db.collection("registration").find(query).count();
const serviceCount = await db
.collection("service-record")
.find(servicQuery)
.count();
return {
userId,
customerCount,
visitCount,
serviceCount,
};
}
// 填充日期间隔
function fillDateGaps(arr, start, end) {
let startDate = new Date(start);
let endDate = new Date(end);
let dateCounts = {};
arr.forEach((item) => {
dateCounts[item._id] = item.count;
});
while (startDate <= endDate) {
let dateString = startDate.toISOString().split("T")[0];
if (!dateCounts[dateString]) {
dateCounts[dateString] = 0;
}
startDate.setDate(startDate.getDate() + 1);
}
let datesArray = Object.entries(dateCounts).map(([dateString, count]) => {
return { _id: dateString, count: count };
});
datesArray.sort((a, b) => new Date(a._id) - new Date(b._id));
return datesArray;
}
async function getTeamCustmerCount(ctx) {
const { corpId, teamIds } = ctx;
if (!corpId || !Array.isArray(teamIds) || teamIds.length === 0) {
return [];
}
try {
const customerCounts = await db
.collection("member")
.aggregate([
{ $match: { teamId: { $in: teamIds } } }, // 查找 teamId 数组中包含任意 teamId 的文档
{ $unwind: "$teamId" }, // 展开 teamId 数组,每个 teamId 成为一个单独的文档
{ $match: { teamId: { $in: teamIds } } }, // 再次匹配这些 teamId 是否在目标队列中
{
$group: {
_id: "$teamId", // 根据 teamId 聚合
count: { $sum: 1 }, // 计算每个 teamId 的数量
},
},
])
.toArray();
return customerCounts;
} catch (e) {
return [];
}
}