guoziyun 9 ماه پیش
والد
کامیت
6ea3402123

+ 254 - 177
oms/dist/src/services/messageRecordService.js

@@ -82,121 +82,76 @@ class MessageRecordService {
     async getOverallStatistics() {
         try {
             const result = await messageRecordModel_1.MessageRecord.aggregate([
-                // 1. 根据状态对消息进行分类
+                // 1. 按状态和inforeground字段分组,计算每个类别的记录数
                 {
                     $group: {
-                        _id: "$status",
+                        _id: { status: "$status", inforeground: "$inforeground" },
                         count: { $sum: 1 },
                     },
                 },
-                // 2. 将结果转换成一个更容易处理的格式
+                // 2. 将数据重组,计算总数、发送成功数、送达数、打开数、展示数
                 {
                     $group: {
                         _id: null,
-                        total_records: { $sum: "$count" },
-                        status_counts: {
-                            $push: {
-                                k: { $toString: "$_id" },
-                                v: "$count",
+                        totalRecords: { $sum: "$count" },
+                        // 发送成功数:status >= 1
+                        sent: {
+                            $sum: { $cond: [{ $gte: ["$_id.status", 1] }, "$count", 0] },
+                        },
+                        // 送达数:status >= 2
+                        delivered: {
+                            $sum: { $cond: [{ $gte: ["$_id.status", 2] }, "$count", 0] },
+                        },
+                        // 打开数:status === 3
+                        opened: {
+                            $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] },
+                        },
+                        failed: {
+                            $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] },
+                        },
+                        // 展示数:status >= 2 并且 inforeground = false
+                        displayCount: {
+                            $sum: {
+                                $cond: [
+                                    {
+                                        $and: [{ $gte: ["$_id.status", 2] }, { $eq: ["$_id.inforeground", false] }],
+                                    },
+                                    "$count",
+                                    0,
+                                ],
                             },
                         },
                     },
                 },
-                // 3. 重新格式化输出,计算所有比率
+                // 3. 计算比率并格式化输出
                 {
                     $project: {
                         _id: 0,
-                        totalRecords: "$total_records",
-                        sent: {
-                            $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "1"] }] }, 0],
+                        totalRecords: "$totalRecords",
+                        sent: "$sent",
+                        delivered: "$delivered",
+                        opened: "$opened",
+                        failed: "$failed",
+                        displayCount: "$displayCount",
+                        // 发送成功率 = sent / totalRecords
+                        sentSuccessRate: {
+                            $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$sent", "$totalRecords"] }],
                         },
-                        delivered: {
-                            $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0],
+                        // 送达率 = delivered / sent
+                        deliveredRate: {
+                            $cond: [{ $eq: ["$sent", 0] }, 0, { $divide: ["$delivered", "$sent"] }],
                         },
-                        opened: {
-                            $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "3"] }] }, 0],
+                        // 展示率 = displayCount / delivered
+                        displayRate: {
+                            $cond: [{ $eq: ["$delivered", 0] }, 0, { $divide: ["$displayCount", "$delivered"] }],
                         },
-                        failed: {
-                            $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "-1"] }] }, 0],
+                        // 点击率 = opened / displayCount
+                        clickThroughRate: {
+                            $cond: [{ $eq: ["$displayCount", 0] }, 0, { $divide: ["$opened", "$displayCount"] }],
                         },
-                        // 新增:发送成功率(发送成功数 + 送达数 + 打开数)/ 总数
-                        sentSuccessRate: {
-                            $cond: [
-                                { $eq: ["$total_records", 0] },
-                                0,
-                                {
-                                    $divide: [
-                                        {
-                                            $sum: [
-                                                { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "1"] }] }, 0] },
-                                                { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                                                { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "3"] }] }, 0] },
-                                            ],
-                                        },
-                                        "$total_records",
-                                    ],
-                                },
-                            ],
-                        },
-                        // 新增:送达率 = 送达数 / (发送成功数 + 送达数)
-                        deliveredRate: {
-                            $cond: [
-                                {
-                                    $eq: [
-                                        {
-                                            $sum: [
-                                                { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "1"] }] }, 0] },
-                                                { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                                            ],
-                                        },
-                                        0,
-                                    ],
-                                },
-                                0,
-                                {
-                                    $divide: [
-                                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                                        {
-                                            $sum: [
-                                                { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "1"] }] }, 0] },
-                                                { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                                            ],
-                                        },
-                                    ],
-                                },
-                            ],
-                        },
-                        // 新增:打开率 = 打开数 / (送达数 + 打开数)
-                        openedRate: {
-                            $cond: [
-                                {
-                                    $eq: [
-                                        {
-                                            $sum: [
-                                                { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                                                { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "3"] }] }, 0] },
-                                            ],
-                                        },
-                                        0,
-                                    ],
-                                },
-                                0,
-                                {
-                                    $divide: [
-                                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "3"] }] }, 0] },
-                                        {
-                                            $sum: [
-                                                { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                                                { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "3"] }] }, 0] },
-                                            ],
-                                        },
-                                    ],
-                                },
-                            ],
-                        },
-                        // Token 失效率
+                        // Token 失效率 = failed / totalRecords
                         tokenInvalidationRate: {
-                            $cond: [{ $eq: ["$total_records", 0] }, 0, { $divide: [{ $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "-1"] }] }, 0] }, "$total_records"] }],
+                            $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$failed", "$totalRecords"] }],
                         },
                     },
                 },
@@ -214,29 +169,51 @@ class MessageRecordService {
     async getStatisticsByActivity() {
         try {
             const results = await messageRecordModel_1.MessageRecord.aggregate([
-                // 1. 根据 activityId 和 status 进行分组
+                // 1. 根据 activityId, status, 和 inforeground 进行分组
                 {
                     $group: {
-                        _id: { activityId: "$activityId", activityName: "$activityName", status: "$status" },
+                        _id: {
+                            activityId: "$activityId",
+                            activityName: "$activityName",
+                            status: "$status",
+                            inforeground: "$inforeground",
+                        },
                         count: { $sum: 1 },
                     },
                 },
                 // 2. 将数据重组,以便按 activityId 汇总
                 {
                     $group: {
-                        _id: "$_id.activityId", // Group by the ID
-                        activityName: { $first: "$_id.activityName" }, // Keep the name
-                        total_sent: { $sum: "$count" },
-                        sent_count: { $sum: { $cond: [{ $eq: ["$_id.status", 1] }, "$count", 0] } },
-                        delivered_count: {
-                            $sum: { $cond: [{ $eq: ["$_id.status", 2] }, "$count", 0] },
-                        },
-                        opened_count: {
+                        _id: "$_id.activityId",
+                        activityName: { $first: "$_id.activityName" },
+                        totalRecords: { $sum: "$count" },
+                        // 发送成功数:status >= 1
+                        sent: {
+                            $sum: { $cond: [{ $gte: ["$_id.status", 1] }, "$count", 0] },
+                        },
+                        // 送达数:status >= 2
+                        delivered: {
+                            $sum: { $cond: [{ $gte: ["$_id.status", 2] }, "$count", 0] },
+                        },
+                        // 打开数:status === 3
+                        opened: {
                             $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] },
                         },
-                        failed_count: {
+                        failed: {
                             $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] },
                         },
+                        // 展示数:status >= 2 并且 inforeground = false
+                        displayCount: {
+                            $sum: {
+                                $cond: [
+                                    {
+                                        $and: [{ $gte: ["$_id.status", 2] }, { $eq: ["$_id.inforeground", false] }],
+                                    },
+                                    "$count",
+                                    0,
+                                ],
+                            },
+                        },
                     },
                 },
                 // 3. 计算比率并格式化输出
@@ -245,22 +222,31 @@ class MessageRecordService {
                         _id: 0,
                         activityId: "$_id",
                         activityName: "$activityName",
-                        totalSent: "$total_sent",
-                        sent: "$sent_count",
-                        delivered: "$delivered_count",
-                        opened: "$opened_count",
-                        failed: "$failed_count",
+                        totalRecords: "$totalRecords",
+                        sent: "$sent",
+                        delivered: "$delivered",
+                        opened: "$opened",
+                        failed: "$failed",
+                        displayCount: "$displayCount",
+                        // 发送成功率 = sent / totalRecords
                         sentSuccessRate: {
-                            $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: [{ $sum: ["$sent_count", "$delivered_count", "$opened_count"] }, "$total_sent"] }],
-                        },
-                        tokenInvalidationRate: {
-                            $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: ["$failed_count", "$total_sent"] }],
+                            $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$sent", "$totalRecords"] }],
                         },
+                        // 送达率 = delivered / sent
                         deliveredRate: {
-                            $cond: [{ $eq: [{ $sum: ["$sent_count", "$delivered_count"] }, 0] }, 0, { $divide: ["$delivered_count", { $sum: ["$sent_count", "$delivered_count"] }] }],
+                            $cond: [{ $eq: ["$sent", 0] }, 0, { $divide: ["$delivered", "$sent"] }],
+                        },
+                        // 展示率 = displayCount / delivered
+                        displayRate: {
+                            $cond: [{ $eq: ["$delivered", 0] }, 0, { $divide: ["$displayCount", "$delivered"] }],
                         },
-                        openedRate: {
-                            $cond: [{ $eq: [{ $sum: ["$delivered_count", "$opened_count"] }, 0] }, 0, { $divide: ["$opened_count", { $sum: ["$delivered_count", "$opened_count"] }] }],
+                        // 点击率 = opened / displayCount
+                        clickThroughRate: {
+                            $cond: [{ $eq: ["$displayCount", 0] }, 0, { $divide: ["$opened", "$displayCount"] }],
+                        },
+                        // Token 失效率 = failed / totalRecords
+                        tokenInvalidationRate: {
+                            $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$failed", "$totalRecords"] }],
                         },
                     },
                 },
@@ -282,10 +268,15 @@ class MessageRecordService {
     async getStatisticsByStrategy() {
         try {
             const results = await messageRecordModel_1.MessageRecord.aggregate([
-                // 1. 根据 strategyId 和 status 进行分组
+                // 1. 根据 strategyId, status, 和 inforeground 进行分组
                 {
                     $group: {
-                        _id: { strategyId: "$strategyId", strategyName: "$strategyName", status: "$status" },
+                        _id: {
+                            strategyId: "$strategyId",
+                            strategyName: "$strategyName",
+                            status: "$status",
+                            inforeground: "$inforeground",
+                        },
                         count: { $sum: 1 },
                     },
                 },
@@ -294,17 +285,34 @@ class MessageRecordService {
                     $group: {
                         _id: "$_id.strategyId",
                         strategyName: { $first: "$_id.strategyName" },
-                        total_sent: { $sum: "$count" },
-                        sent_count: { $sum: { $cond: [{ $eq: ["$_id.status", 1] }, "$count", 0] } },
-                        delivered_count: {
-                            $sum: { $cond: [{ $eq: ["$_id.status", 2] }, "$count", 0] },
+                        totalRecords: { $sum: "$count" },
+                        // 发送成功数:status >= 1
+                        sent: {
+                            $sum: { $cond: [{ $gte: ["$_id.status", 1] }, "$count", 0] },
+                        },
+                        // 送达数:status >= 2
+                        delivered: {
+                            $sum: { $cond: [{ $gte: ["$_id.status", 2] }, "$count", 0] },
                         },
-                        opened_count: {
+                        // 打开数:status === 3
+                        opened: {
                             $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] },
                         },
-                        failed_count: {
+                        failed: {
                             $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] },
                         },
+                        // 展示数:status >= 2 并且 inforeground = false
+                        displayCount: {
+                            $sum: {
+                                $cond: [
+                                    {
+                                        $and: [{ $gte: ["$_id.status", 2] }, { $eq: ["$_id.inforeground", false] }],
+                                    },
+                                    "$count",
+                                    0,
+                                ],
+                            },
+                        },
                     },
                 },
                 // 3. 计算比率并格式化输出
@@ -313,22 +321,31 @@ class MessageRecordService {
                         _id: 0,
                         strategyId: "$_id",
                         strategyName: "$strategyName",
-                        totalSent: "$total_sent",
-                        sent: "$sent_count",
-                        delivered: "$delivered_count",
-                        opened: "$opened_count",
-                        failed: "$failed_count",
+                        totalRecords: "$totalRecords",
+                        sent: "$sent",
+                        delivered: "$delivered",
+                        opened: "$opened",
+                        failed: "$failed",
+                        displayCount: "$displayCount",
+                        // 发送成功率 = sent / totalRecords
                         sentSuccessRate: {
-                            $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: [{ $sum: ["$sent_count", "$delivered_count", "$opened_count"] }, "$total_sent"] }],
-                        },
-                        tokenInvalidationRate: {
-                            $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: ["$failed_count", "$total_sent"] }],
+                            $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$sent", "$totalRecords"] }],
                         },
+                        // 送达率 = delivered / sent
                         deliveredRate: {
-                            $cond: [{ $eq: [{ $sum: ["$sent_count", "$delivered_count"] }, 0] }, 0, { $divide: ["$delivered_count", { $sum: ["$sent_count", "$delivered_count"] }] }],
+                            $cond: [{ $eq: ["$sent", 0] }, 0, { $divide: ["$delivered", "$sent"] }],
                         },
-                        openedRate: {
-                            $cond: [{ $eq: [{ $sum: ["$delivered_count", "$opened_count"] }, 0] }, 0, { $divide: ["$opened_count", { $sum: ["$delivered_count", "$opened_count"] }] }],
+                        // 展示率 = displayCount / delivered
+                        displayRate: {
+                            $cond: [{ $eq: ["$delivered", 0] }, 0, { $divide: ["$displayCount", "$delivered"] }],
+                        },
+                        // 点击率 = opened / displayCount
+                        clickThroughRate: {
+                            $cond: [{ $eq: ["$displayCount", 0] }, 0, { $divide: ["$opened", "$displayCount"] }],
+                        },
+                        // Token 失效率 = failed / totalRecords
+                        tokenInvalidationRate: {
+                            $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$failed", "$totalRecords"] }],
                         },
                     },
                 },
@@ -350,10 +367,15 @@ class MessageRecordService {
     async getStatisticsByTemplate() {
         try {
             const results = await messageRecordModel_1.MessageRecord.aggregate([
-                // 1. 根据 templateId 和 status 进行分组
+                // 1. 根据 templateId, status, 和 inforeground 进行分组
                 {
                     $group: {
-                        _id: { templateId: "$templateId", templateName: "$templateName", status: "$status" },
+                        _id: {
+                            templateId: "$templateId",
+                            templateName: "$templateName",
+                            status: "$status",
+                            inforeground: "$inforeground",
+                        },
                         count: { $sum: 1 },
                     },
                 },
@@ -362,17 +384,34 @@ class MessageRecordService {
                     $group: {
                         _id: "$_id.templateId",
                         templateName: { $first: "$_id.templateName" },
-                        total_sent: { $sum: "$count" },
-                        sent_count: { $sum: { $cond: [{ $eq: ["$_id.status", 1] }, "$count", 0] } },
-                        delivered_count: {
-                            $sum: { $cond: [{ $eq: ["$_id.status", 2] }, "$count", 0] },
+                        totalRecords: { $sum: "$count" },
+                        // 发送成功数:status >= 1
+                        sent: {
+                            $sum: { $cond: [{ $gte: ["$_id.status", 1] }, "$count", 0] },
                         },
-                        opened_count: {
+                        // 送达数:status >= 2
+                        delivered: {
+                            $sum: { $cond: [{ $gte: ["$_id.status", 2] }, "$count", 0] },
+                        },
+                        // 打开数:status === 3
+                        opened: {
                             $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] },
                         },
-                        failed_count: {
+                        failed: {
                             $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] },
                         },
+                        // 展示数:status >= 2 并且 inforeground = false
+                        displayCount: {
+                            $sum: {
+                                $cond: [
+                                    {
+                                        $and: [{ $gte: ["$_id.status", 2] }, { $eq: ["$_id.inforeground", false] }],
+                                    },
+                                    "$count",
+                                    0,
+                                ],
+                            },
+                        },
                     },
                 },
                 // 3. 计算比率并格式化输出
@@ -381,22 +420,31 @@ class MessageRecordService {
                         _id: 0,
                         templateId: "$_id",
                         templateName: "$templateName",
-                        totalSent: "$total_sent",
-                        sent: "$sent_count",
-                        delivered: "$delivered_count",
-                        opened: "$opened_count",
-                        failed: "$failed_count",
+                        totalRecords: "$totalRecords",
+                        sent: "$sent",
+                        delivered: "$delivered",
+                        opened: "$opened",
+                        failed: "$failed",
+                        displayCount: "$displayCount",
+                        // 发送成功率 = sent / totalRecords
                         sentSuccessRate: {
-                            $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: [{ $sum: ["$sent_count", "$delivered_count", "$opened_count"] }, "$total_sent"] }],
-                        },
-                        tokenInvalidationRate: {
-                            $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: ["$failed_count", "$total_sent"] }],
+                            $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$sent", "$totalRecords"] }],
                         },
+                        // 送达率 = delivered / sent
                         deliveredRate: {
-                            $cond: [{ $eq: [{ $sum: ["$sent_count", "$delivered_count"] }, 0] }, 0, { $divide: ["$delivered_count", { $sum: ["$sent_count", "$delivered_count"] }] }],
+                            $cond: [{ $eq: ["$sent", 0] }, 0, { $divide: ["$delivered", "$sent"] }],
                         },
-                        openedRate: {
-                            $cond: [{ $eq: [{ $sum: ["$delivered_count", "$opened_count"] }, 0] }, 0, { $divide: ["$opened_count", { $sum: ["$delivered_count", "$opened_count"] }] }],
+                        // 展示率 = displayCount / delivered
+                        displayRate: {
+                            $cond: [{ $eq: ["$delivered", 0] }, 0, { $divide: ["$displayCount", "$delivered"] }],
+                        },
+                        // 点击率 = opened / displayCount
+                        clickThroughRate: {
+                            $cond: [{ $eq: ["$displayCount", 0] }, 0, { $divide: ["$opened", "$displayCount"] }],
+                        },
+                        // Token 失效率 = failed / totalRecords
+                        tokenInvalidationRate: {
+                            $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$failed", "$totalRecords"] }],
                         },
                     },
                 },
@@ -424,12 +472,13 @@ class MessageRecordService {
                             $dateTrunc: { date: "$actualSendAt", unit: "day", timezone: "America/Los_Angeles" },
                         },
                         status: "$status",
+                        inforeground: "$inforeground",
                     },
                 },
-                // 2. 根据日期和状态进行分组
+                // 2. 根据日期、状态和 inforeground 进行分组
                 {
                     $group: {
-                        _id: { date: "$date", status: "$status" },
+                        _id: { date: "$date", status: "$status", inforeground: "$inforeground" },
                         count: { $sum: 1 },
                     },
                 },
@@ -437,11 +486,34 @@ class MessageRecordService {
                 {
                     $group: {
                         _id: "$_id.date",
-                        totalSent: { $sum: "$count" },
-                        sent: { $sum: { $cond: [{ $eq: ["$_id.status", 1] }, "$count", 0] } },
-                        delivered: { $sum: { $cond: [{ $eq: ["$_id.status", 2] }, "$count", 0] } },
-                        opened: { $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] } },
-                        failed: { $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] } },
+                        totalRecords: { $sum: "$count" },
+                        // 发送成功数:status >= 1
+                        sent: {
+                            $sum: { $cond: [{ $gte: ["$_id.status", 1] }, "$count", 0] },
+                        },
+                        // 送达数:status >= 2
+                        delivered: {
+                            $sum: { $cond: [{ $gte: ["$_id.status", 2] }, "$count", 0] },
+                        },
+                        // 打开数:status === 3
+                        opened: {
+                            $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] },
+                        },
+                        failed: {
+                            $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] },
+                        },
+                        // 展示数:status >= 2 并且 inforeground = false
+                        displayCount: {
+                            $sum: {
+                                $cond: [
+                                    {
+                                        $and: [{ $gte: ["$_id.status", 2] }, { $eq: ["$_id.inforeground", false] }],
+                                    },
+                                    "$count",
+                                    0,
+                                ],
+                            },
+                        },
                     },
                 },
                 // 4. 计算比率并格式化输出
@@ -449,26 +521,31 @@ class MessageRecordService {
                     $project: {
                         _id: 0,
                         date: "$_id",
-                        totalSent: "$totalSent",
+                        totalRecords: "$totalRecords",
                         sent: "$sent",
                         delivered: "$delivered",
                         opened: "$opened",
                         failed: "$failed",
-                        // Sent success rate = (sent + delivered + opened) / total
+                        displayCount: "$displayCount",
+                        // 发送成功率 = sent / totalRecords
                         sentSuccessRate: {
-                            $cond: [{ $eq: ["$totalSent", 0] }, 0, { $divide: [{ $sum: ["$sent", "$delivered", "$opened"] }, "$totalSent"] }],
+                            $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$sent", "$totalRecords"] }],
                         },
-                        // Delivered rate = delivered / (sent + delivered)
+                        // 送达率 = delivered / sent
                         deliveredRate: {
-                            $cond: [{ $eq: [{ $sum: ["$sent", "$delivered"] }, 0] }, 0, { $divide: ["$delivered", { $sum: ["$sent", "$delivered"] }] }],
+                            $cond: [{ $eq: ["$sent", 0] }, 0, { $divide: ["$delivered", "$sent"] }],
+                        },
+                        // 展示率 = displayCount / delivered
+                        displayRate: {
+                            $cond: [{ $eq: ["$delivered", 0] }, 0, { $divide: ["$displayCount", "$delivered"] }],
                         },
-                        // Opened rate = opened / (delivered + opened)
-                        openedRate: {
-                            $cond: [{ $eq: [{ $sum: ["$delivered", "$opened"] }, 0] }, 0, { $divide: ["$opened", { $sum: ["$delivered", "$opened"] }] }],
+                        // 点击率 = opened / displayCount
+                        clickThroughRate: {
+                            $cond: [{ $eq: ["$displayCount", 0] }, 0, { $divide: ["$opened", "$displayCount"] }],
                         },
                         // Token invalidation rate
                         tokenInvalidationRate: {
-                            $cond: [{ $eq: ["$totalSent", 0] }, 0, { $divide: ["$failed", "$totalSent"] }],
+                            $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$failed", "$totalRecords"] }],
                         },
                     },
                 },
@@ -484,14 +561,14 @@ class MessageRecordService {
             return [];
         }
     }
-    // 消息生命周期分析, 利用 plannedSendAt、actualSendAt、deliveredAt 和 openedAt 字段,可以分析消息从计划到被用户打开的整个生命周期。
+    // 消息生命周期分析
     async getAverageDeliveryTime() {
         try {
             const result = await messageRecordModel_1.MessageRecord.aggregate([
-                // 1. 只筛选出已送达的消息(status = 2 或 3
+                // 1. 只筛选出已送达的消息(status >= 2)
                 {
                     $match: {
-                        status: { $in: [2, 3] },
+                        status: { $gte: 2 },
                         actualSendAt: { $exists: true, $ne: null },
                         deliveredAt: { $exists: true, $ne: null },
                     },

+ 1 - 1
oms/public/app/index.html

@@ -9,5 +9,5 @@
   <style>body,html{width:100%;height:100%}*,:after,:before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}@-ms-viewport{width:device-width}body{margin:0;color:#000000d9;font-size:14px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-variant:tabular-nums;line-height:1.5715;background-color:#fff;font-feature-settings:"tnum"}html{--antd-wave-shadow-color:#1890ff;--scroll-bar:0}</style><link rel="stylesheet" href="styles-LXBSU6DF.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles-LXBSU6DF.css"></noscript></head>
   <body>
     <app-root></app-root>
-  <script src="polyfills-B6TNHZQ6.js" type="module"></script><script src="main-V2NUZO54.js" type="module"></script></body>
+  <script src="polyfills-B6TNHZQ6.js" type="module"></script><script src="main-5OJG5IYB.js" type="module"></script></body>
 </html>

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
oms/public/app/main-5OJG5IYB.js


+ 0 - 559
oms/src/services/messageRecordService copy.ts

@@ -1,559 +0,0 @@
-// oms/src/services/messageRecordService.ts
-
-import { MessageRecord, IMessageRecord } from "../models/messageRecordModel";
-import { MessageActivity } from "../models/messageActivityModel";
-import { MessageStrategy } from "../models/messageStrategyModel";
-import { MessageTemplate } from "../models/messageTemplateModel";
-
-export class MessageRecordService {
-  /**
-   * Creates a new message push record.
-   * @param recordData Message record data.
-   * @returns The newly created message record object.
-   */
-  public async createMessageRecord(recordData: IMessageRecord): Promise<IMessageRecord> {
-    const newRecord = new MessageRecord(recordData);
-    return await newRecord.save();
-  }
-
-  /**
-   * Gets paginated message records with filtering and sorting support.
-   * @param page Page number.
-   * @param limit Number of records per page.
-   * @param filters Filter conditions.
-   * @param sortField Field to sort by.
-   * @param sortOrder Sort order ('asc' or 'desc').
-   * @returns An object containing records and the total count.
-   */
-  public async getPaginatedRecords(
-    page: number = 1,
-    limit: number = 10,
-    filters: { [key: string]: any } = {},
-    sortField: string = "createdAt",
-    sortOrder: "asc" | "desc" = "desc"
-  ): Promise<{ records: IMessageRecord[]; total: number }> {
-    // Build the query conditions
-    const query: any = {};
-    if (filters.uid) {
-      query.uid = filters.uid;
-    }
-    if (filters.activityName) {
-      query.activityName = filters.activityName;
-    }
-    if (filters.templateName) {
-      query.templateName = filters.templateName;
-    }
-    if (filters.status !== undefined) {
-      query.status = filters.status;
-    }
-
-    const sort: any = {};
-    sort[sortField] = sortOrder === "asc" ? 1 : -1;
-
-    const skip = (page - 1) * limit;
-
-    const records = await MessageRecord.find(query).sort(sort).skip(skip).limit(limit);
-
-    const total = await MessageRecord.countDocuments(query);
-
-    return { records, total };
-  }
-
-  /**
-   * Gets all message records for a specific user UID.
-   * @param uid User UID.
-   * @returns A list of message records.
-   */
-  public async getRecordsByUid(uid: string): Promise<IMessageRecord[]> {
-    return await MessageRecord.find({ uid }).sort({ createdAt: -1 });
-  }
-
-  /**
-   * Gets all message records related to a specific activity ID.
-   * @param activityId Message activity ID.
-   * @returns A list of message records.
-   */
-  public async getRecordsByActivityId(activityId: string): Promise<IMessageRecord[]> {
-    return await MessageRecord.find({ activityId }).sort({ createdAt: -1 });
-  }
-
-  /**
-   * Gets a single message record by ID.
-   * @param recordId Message record ID.
-   * @returns The message record object or null.
-   */
-  public async getSingleRecord(recordId: string): Promise<IMessageRecord | null> {
-    return await MessageRecord.findById(recordId);
-  }
-
-  /**
-   * Updates the status of a message record.
-   * @param recordId Message record ID.
-   * @param updateData Data to update.
-   * @returns The updated message record object.
-   */
-  public async updateMessageRecord(recordId: string, updateData: Partial<IMessageRecord>): Promise<IMessageRecord | null> {
-    return await MessageRecord.findByIdAndUpdate(recordId, updateData, { new: true });
-  }
-
-  /**
-   * Gets overall message push statistics.
-   */
-  public async getOverallStatistics() {
-    try {
-      const result = await MessageRecord.aggregate([
-        // 1. Group messages by status
-        {
-          $group: {
-            _id: "$status",
-            count: { $sum: 1 },
-          },
-        },
-        // 2. Transform the result into a more manageable format
-        {
-          $group: {
-            _id: null,
-            total_records: { $sum: "$count" },
-            status_counts: {
-              $push: {
-                k: { $toString: "$_id" },
-                v: "$count",
-              },
-            },
-          },
-        },
-        // 3. Reformat the output and calculate all rates
-        {
-          $project: {
-            _id: 0,
-            totalRecords: "$total_records",
-            sent: {
-              $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "1"] }] }, 0],
-            },
-            delivered: {
-              $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0],
-            },
-            opened: {
-              $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "3"] }] }, 0],
-            },
-            failed: {
-              $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "-1"] }] }, 0],
-            },
-            // Sent success rate = (sent + delivered + opened) / total
-            sentSuccessRate: {
-              $cond: [
-                { $eq: ["$total_records", 0] },
-                0,
-                {
-                  $divide: [
-                    {
-                      $sum: [
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "1"] }] }, 0] },
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "3"] }] }, 0] },
-                      ],
-                    },
-                    "$total_records",
-                  ],
-                },
-              ],
-            },
-            // Delivered rate = delivered / (sent + delivered)
-            deliveredRate: {
-              $cond: [
-                {
-                  $eq: [
-                    {
-                      $sum: [
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "1"] }] }, 0] },
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                      ],
-                    },
-                    0,
-                  ],
-                },
-                0,
-                {
-                  $divide: [
-                    { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                    {
-                      $sum: [
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "1"] }] }, 0] },
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                      ],
-                    },
-                  ],
-                },
-              ],
-            },
-            // Opened rate = opened / (delivered + opened)
-            openedRate: {
-              $cond: [
-                {
-                  $eq: [
-                    {
-                      $sum: [
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "3"] }] }, 0] },
-                      ],
-                    },
-                    0,
-                  ],
-                },
-                0,
-                {
-                  $divide: [
-                    { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "3"] }] }, 0] },
-                    {
-                      $sum: [
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "3"] }] }, 0] },
-                      ],
-                    },
-                  ],
-                },
-              ],
-            },
-            // Token invalidation rate
-            tokenInvalidationRate: {
-              $cond: [{ $eq: ["$total_records", 0] }, 0, { $divide: [{ $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "-1"] }] }, 0] }, "$total_records"] }],
-            },
-          },
-        },
-      ]);
-
-      return result[0];
-    } catch (error) {
-      console.error("Error fetching overall statistics:", error);
-      return null;
-    }
-  }
-
-  /**
-   * Gets message statistics grouped by activity.
-   */
-  public async getStatisticsByActivity() {
-    try {
-      const results = await MessageRecord.aggregate([
-        // 1. Group by both activityId and status
-        {
-          $group: {
-            _id: { activityId: "$activityId", activityName: "$activityName", status: "$status" },
-            count: { $sum: 1 },
-          },
-        },
-        // 2. Regroup by activityId to summarize counts and get the activityName
-        {
-          $group: {
-            _id: "$_id.activityId", // Group by the ID
-            activityName: { $first: "$_id.activityName" }, // Keep the name
-            total_sent: { $sum: "$count" },
-            sent_count: { $sum: { $cond: [{ $eq: ["$_id.status", 1] }, "$count", 0] } },
-            delivered_count: {
-              $sum: { $cond: [{ $eq: ["$_id.status", 2] }, "$count", 0] },
-            },
-            opened_count: {
-              $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] },
-            },
-            failed_count: {
-              $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] },
-            },
-          },
-        },
-        // 3. Calculate rates and format the output
-        {
-          $project: {
-            _id: 0,
-            activityId: "$_id",
-            activityName: "$activityName",
-            totalSent: "$total_sent",
-            sent: "$sent_count",
-            delivered: "$delivered_count",
-            opened: "$opened_count",
-            failed: "$failed_count",
-            sentSuccessRate: {
-              $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: [{ $sum: ["$sent_count", "$delivered_count", "$opened_count"] }, "$total_sent"] }],
-            },
-            tokenInvalidationRate: {
-              $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: ["$failed_count", "$total_sent"] }],
-            },
-            deliveredRate: {
-              $cond: [{ $eq: [{ $sum: ["$sent_count", "$delivered_count"] }, 0] }, 0, { $divide: ["$delivered_count", { $sum: ["$sent_count", "$delivered_count"] }] }],
-            },
-            openedRate: {
-              $cond: [{ $eq: [{ $sum: ["$delivered_count", "$opened_count"] }, 0] }, 0, { $divide: ["$opened_count", { $sum: ["$delivered_count", "$opened_count"] }] }],
-            },
-          },
-        },
-        // 4. Sort by deliveredRate in descending order
-        {
-          $sort: { deliveredRate: -1 },
-        },
-      ]);
-
-      return results;
-    } catch (error) {
-      console.error("Error fetching statistics by activity:", error);
-      return [];
-    }
-  }
-
-  /**
-   * Gets message statistics grouped by strategy.
-   */
-  public async getStatisticsByStrategy() {
-    try {
-      const results = await MessageRecord.aggregate([
-        // 1. Group by both strategyId and status
-        {
-          $group: {
-            _id: { strategyId: "$strategyId", strategyName: "$strategyName", status: "$status" },
-            count: { $sum: 1 },
-          },
-        },
-        // 2. Regroup by strategyId to summarize counts and get the strategyName
-        {
-          $group: {
-            _id: "$_id.strategyId",
-            strategyName: { $first: "$_id.strategyName" },
-            total_sent: { $sum: "$count" },
-            sent_count: { $sum: { $cond: [{ $eq: ["$_id.status", 1] }, "$count", 0] } },
-            delivered_count: {
-              $sum: { $cond: [{ $eq: ["$_id.status", 2] }, "$count", 0] },
-            },
-            opened_count: {
-              $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] },
-            },
-            failed_count: {
-              $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] },
-            },
-          },
-        },
-        // 3. Calculate rates and format the output
-        {
-          $project: {
-            _id: 0,
-            strategyId: "$_id",
-            strategyName: "$strategyName",
-            totalSent: "$total_sent",
-            sent: "$sent_count",
-            delivered: "$delivered_count",
-            opened: "$opened_count",
-            failed: "$failed_count",
-            sentSuccessRate: {
-              $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: [{ $sum: ["$sent_count", "$delivered_count", "$opened_count"] }, "$total_sent"] }],
-            },
-            tokenInvalidationRate: {
-              $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: ["$failed_count", "$total_sent"] }],
-            },
-            deliveredRate: {
-              $cond: [{ $eq: [{ $sum: ["$sent_count", "$delivered_count"] }, 0] }, 0, { $divide: ["$delivered_count", { $sum: ["$sent_count", "$delivered_count"] }] }],
-            },
-            openedRate: {
-              $cond: [{ $eq: [{ $sum: ["$delivered_count", "$opened_count"] }, 0] }, 0, { $divide: ["$opened_count", { $sum: ["$delivered_count", "$opened_count"] }] }],
-            },
-          },
-        },
-        // 4. Sort by deliveredRate in descending order
-        {
-          $sort: { deliveredRate: -1 },
-        },
-      ]);
-
-      return results;
-    } catch (error) {
-      console.error("Error fetching statistics by strategy:", error);
-      return [];
-    }
-  }
-
-  /**
-   * Gets message statistics grouped by template.
-   */
-  public async getStatisticsByTemplate() {
-    try {
-      const results = await MessageRecord.aggregate([
-        // 1. Group by both templateId and status
-        {
-          $group: {
-            _id: { templateId: "$templateId", templateName: "$templateName", status: "$status" },
-            count: { $sum: 1 },
-          },
-        },
-        // 2. Regroup by templateId to summarize counts and get the templateName
-        {
-          $group: {
-            _id: "$_id.templateId",
-            templateName: { $first: "$_id.templateName" },
-            total_sent: { $sum: "$count" },
-            sent_count: { $sum: { $cond: [{ $eq: ["$_id.status", 1] }, "$count", 0] } },
-            delivered_count: {
-              $sum: { $cond: [{ $eq: ["$_id.status", 2] }, "$count", 0] },
-            },
-            opened_count: {
-              $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] },
-            },
-            failed_count: {
-              $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] },
-            },
-          },
-        },
-        // 3. Calculate rates and format the output
-        {
-          $project: {
-            _id: 0,
-            templateId: "$_id",
-            templateName: "$templateName",
-            totalSent: "$total_sent",
-            sent: "$sent_count",
-            delivered: "$delivered_count",
-            opened: "$opened_count",
-            failed: "$failed_count",
-            sentSuccessRate: {
-              $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: [{ $sum: ["$sent_count", "$delivered_count", "$opened_count"] }, "$total_sent"] }],
-            },
-            tokenInvalidationRate: {
-              $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: ["$failed_count", "$total_sent"] }],
-            },
-            deliveredRate: {
-              $cond: [{ $eq: [{ $sum: ["$sent_count", "$delivered_count"] }, 0] }, 0, { $divide: ["$delivered_count", { $sum: ["$sent_count", "$delivered_count"] }] }],
-            },
-            openedRate: {
-              $cond: [{ $eq: [{ $sum: ["$delivered_count", "$opened_count"] }, 0] }, 0, { $divide: ["$opened_count", { $sum: ["$delivered_count", "$opened_count"] }] }],
-            },
-          },
-        },
-        // 4. Sort by deliveredRate in descending order
-        {
-          $sort: { deliveredRate: -1 },
-        },
-      ]);
-
-      return results;
-    } catch (error) {
-      console.error("Error fetching statistics by template:", error);
-      return [];
-    }
-  }
-
-  /**
-   * Gets daily message sending trends.
-   */
-  public async getDailySentTrends() {
-    try {
-      const results = await MessageRecord.aggregate([
-        // 1. Truncate actualSendAt to the day, ignoring time
-        {
-          $project: {
-            _id: 0,
-            date: {
-              $dateTrunc: { date: "$actualSendAt", unit: "day", timezone: "America/Los_Angeles" },
-            },
-            status: "$status",
-          },
-        },
-        // 2. Group by date and status
-        {
-          $group: {
-            _id: { date: "$date", status: "$status" },
-            count: { $sum: 1 },
-          },
-        },
-        // 3. Regroup to summarize counts by date
-        {
-          $group: {
-            _id: "$_id.date",
-            totalSent: { $sum: "$count" },
-            sent: { $sum: { $cond: [{ $eq: ["$_id.status", 1] }, "$count", 0] } },
-            delivered: { $sum: { $cond: [{ $eq: ["$_id.status", 2] }, "$count", 0] } },
-            opened: { $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] } },
-            failed: { $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] } },
-          },
-        },
-        // 4. Calculate rates and format the output
-        {
-          $project: {
-            _id: 0,
-            date: "$_id",
-            totalSent: "$totalSent",
-            sent: "$sent",
-            delivered: "$delivered",
-            opened: "$opened",
-            failed: "$failed",
-            // Sent success rate = (sent + delivered + opened) / total
-            sentSuccessRate: {
-              $cond: [{ $eq: ["$totalSent", 0] }, 0, { $divide: [{ $sum: ["$sent", "$delivered", "$opened"] }, "$totalSent"] }],
-            },
-            // Delivered rate = delivered / (sent + delivered)
-            deliveredRate: {
-              $cond: [{ $eq: [{ $sum: ["$sent", "$delivered"] }, 0] }, 0, { $divide: ["$delivered", { $sum: ["$sent", "$delivered"] }] }],
-            },
-            // Opened rate = opened / (delivered + opened)
-            openedRate: {
-              $cond: [{ $eq: [{ $sum: ["$delivered", "$opened"] }, 0] }, 0, { $divide: ["$opened", { $sum: ["$delivered", "$opened"] }] }],
-            },
-            // Token invalidation rate
-            tokenInvalidationRate: {
-              $cond: [{ $eq: ["$totalSent", 0] }, 0, { $divide: ["$failed", "$totalSent"] }],
-            },
-          },
-        },
-        // 5. Sort by date in ascending order
-        {
-          $sort: { date: 1 },
-        },
-      ]);
-
-      return results;
-    } catch (error) {
-      console.error("Error fetching daily sent trends:", error);
-      return [];
-    }
-  }
-
-  /**
-   * Calculates the average delivery time.
-   */
-  public async getAverageDeliveryTime() {
-    try {
-      const result = await MessageRecord.aggregate([
-        // 1. Filter for delivered messages (status 2 or 3) with existing timestamps
-        {
-          $match: {
-            status: { $in: [2, 3] },
-            actualSendAt: { $exists: true, $ne: null },
-            deliveredAt: { $exists: true, $ne: null },
-          },
-        },
-        // 2. Calculate the time difference (in milliseconds) from send to delivery
-        {
-          $addFields: {
-            time_to_deliver: {
-              $subtract: ["$deliveredAt", "$actualSendAt"],
-            },
-          },
-        },
-        // 3. Calculate the average time
-        {
-          $group: {
-            _id: null,
-            avg_time_to_deliver_ms: { $avg: "$time_to_deliver" },
-          },
-        },
-        // 4. Convert to seconds for readability
-        {
-          $project: {
-            _id: 0,
-            averageTimeToDeliverInSeconds: {
-              $divide: ["$avg_time_to_deliver_ms", 1000],
-            },
-          },
-        },
-      ]);
-      return result[0];
-    } catch (error) {
-      console.error("Error calculating average delivery time:", error);
-      return null;
-    }
-  }
-}

+ 254 - 181
oms/src/services/messageRecordService.ts

@@ -97,126 +97,80 @@ export class MessageRecordService {
   public async getOverallStatistics() {
     try {
       const result = await MessageRecord.aggregate([
-        // 1. 根据状态对消息进行分类
+        // 1. 按状态和inforeground字段分组,计算每个类别的记录数
         {
           $group: {
-            _id: "$status",
+            _id: { status: "$status", inforeground: "$inforeground" },
             count: { $sum: 1 },
           },
         },
-        // 2. 将结果转换成一个更容易处理的格式
+        // 2. 将数据重组,计算总数、发送成功数、送达数、打开数、展示数
         {
           $group: {
             _id: null,
-            total_records: { $sum: "$count" },
-            status_counts: {
-              $push: {
-                k: { $toString: "$_id" },
-                v: "$count",
+            totalRecords: { $sum: "$count" },
+            // 发送成功数:status >= 1
+            sent: {
+              $sum: { $cond: [{ $gte: ["$_id.status", 1] }, "$count", 0] },
+            },
+            // 送达数:status >= 2
+            delivered: {
+              $sum: { $cond: [{ $gte: ["$_id.status", 2] }, "$count", 0] },
+            },
+            // 打开数:status === 3
+            opened: {
+              $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] },
+            },
+            failed: {
+              $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] },
+            },
+            // 展示数:status >= 2 并且 inforeground = false
+            displayCount: {
+              $sum: {
+                $cond: [
+                  {
+                    $and: [{ $gte: ["$_id.status", 2] }, { $eq: ["$_id.inforeground", false] }],
+                  },
+                  "$count",
+                  0,
+                ],
               },
             },
           },
         },
-        // 3. 重新格式化输出,计算所有比率
+        // 3. 计算比率并格式化输出
         {
           $project: {
             _id: 0,
-            totalRecords: "$total_records",
-            sent: {
-              $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "1"] }] }, 0],
+            totalRecords: "$totalRecords",
+            sent: "$sent",
+            delivered: "$delivered",
+            opened: "$opened",
+            failed: "$failed",
+            displayCount: "$displayCount",
+            // 发送成功率 = sent / totalRecords
+            sentSuccessRate: {
+              $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$sent", "$totalRecords"] }],
             },
-            delivered: {
-              $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0],
+            // 送达率 = delivered / sent
+            deliveredRate: {
+              $cond: [{ $eq: ["$sent", 0] }, 0, { $divide: ["$delivered", "$sent"] }],
             },
-            opened: {
-              $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "3"] }] }, 0],
+            // 展示率 = displayCount / delivered
+            displayRate: {
+              $cond: [{ $eq: ["$delivered", 0] }, 0, { $divide: ["$displayCount", "$delivered"] }],
             },
-            failed: {
-              $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "-1"] }] }, 0],
+            // 点击率 = opened / displayCount
+            clickThroughRate: {
+              $cond: [{ $eq: ["$displayCount", 0] }, 0, { $divide: ["$opened", "$displayCount"] }],
             },
-            // 新增:发送成功率(发送成功数 + 送达数 + 打开数)/ 总数
-            sentSuccessRate: {
-              $cond: [
-                { $eq: ["$total_records", 0] },
-                0,
-                {
-                  $divide: [
-                    {
-                      $sum: [
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "1"] }] }, 0] },
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "3"] }] }, 0] },
-                      ],
-                    },
-                    "$total_records",
-                  ],
-                },
-              ],
-            },
-            // 新增:送达率 = 送达数 / (发送成功数 + 送达数)
-            deliveredRate: {
-              $cond: [
-                {
-                  $eq: [
-                    {
-                      $sum: [
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "1"] }] }, 0] },
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                      ],
-                    },
-                    0,
-                  ],
-                },
-                0,
-                {
-                  $divide: [
-                    { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                    {
-                      $sum: [
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "1"] }] }, 0] },
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                      ],
-                    },
-                  ],
-                },
-              ],
-            },
-            // 新增:打开率 = 打开数 / (送达数 + 打开数)
-            openedRate: {
-              $cond: [
-                {
-                  $eq: [
-                    {
-                      $sum: [
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "3"] }] }, 0] },
-                      ],
-                    },
-                    0,
-                  ],
-                },
-                0,
-                {
-                  $divide: [
-                    { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "3"] }] }, 0] },
-                    {
-                      $sum: [
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "2"] }] }, 0] },
-                        { $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "3"] }] }, 0] },
-                      ],
-                    },
-                  ],
-                },
-              ],
-            },
-            // Token 失效率
+            // Token 失效率 = failed / totalRecords
             tokenInvalidationRate: {
-              $cond: [{ $eq: ["$total_records", 0] }, 0, { $divide: [{ $ifNull: [{ $arrayElemAt: ["$status_counts.v", { $indexOfArray: ["$status_counts.k", "-1"] }] }, 0] }, "$total_records"] }],
+              $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$failed", "$totalRecords"] }],
             },
           },
         },
       ]);
-
       return result[0];
     } catch (error) {
       console.error("Error fetching overall statistics:", error);
@@ -230,29 +184,51 @@ export class MessageRecordService {
   public async getStatisticsByActivity() {
     try {
       const results = await MessageRecord.aggregate([
-        // 1. 根据 activityId 和 status 进行分组
+        // 1. 根据 activityId, status, 和 inforeground 进行分组
         {
           $group: {
-            _id: { activityId: "$activityId", activityName: "$activityName", status: "$status" },
+            _id: {
+              activityId: "$activityId",
+              activityName: "$activityName",
+              status: "$status",
+              inforeground: "$inforeground",
+            },
             count: { $sum: 1 },
           },
         },
         // 2. 将数据重组,以便按 activityId 汇总
         {
           $group: {
-            _id: "$_id.activityId", // Group by the ID
-            activityName: { $first: "$_id.activityName" }, // Keep the name
-            total_sent: { $sum: "$count" },
-            sent_count: { $sum: { $cond: [{ $eq: ["$_id.status", 1] }, "$count", 0] } },
-            delivered_count: {
-              $sum: { $cond: [{ $eq: ["$_id.status", 2] }, "$count", 0] },
-            },
-            opened_count: {
+            _id: "$_id.activityId",
+            activityName: { $first: "$_id.activityName" },
+            totalRecords: { $sum: "$count" },
+            // 发送成功数:status >= 1
+            sent: {
+              $sum: { $cond: [{ $gte: ["$_id.status", 1] }, "$count", 0] },
+            },
+            // 送达数:status >= 2
+            delivered: {
+              $sum: { $cond: [{ $gte: ["$_id.status", 2] }, "$count", 0] },
+            },
+            // 打开数:status === 3
+            opened: {
               $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] },
             },
-            failed_count: {
+            failed: {
               $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] },
             },
+            // 展示数:status >= 2 并且 inforeground = false
+            displayCount: {
+              $sum: {
+                $cond: [
+                  {
+                    $and: [{ $gte: ["$_id.status", 2] }, { $eq: ["$_id.inforeground", false] }],
+                  },
+                  "$count",
+                  0,
+                ],
+              },
+            },
           },
         },
         // 3. 计算比率并格式化输出
@@ -261,22 +237,31 @@ export class MessageRecordService {
             _id: 0,
             activityId: "$_id",
             activityName: "$activityName",
-            totalSent: "$total_sent",
-            sent: "$sent_count",
-            delivered: "$delivered_count",
-            opened: "$opened_count",
-            failed: "$failed_count",
+            totalRecords: "$totalRecords",
+            sent: "$sent",
+            delivered: "$delivered",
+            opened: "$opened",
+            failed: "$failed",
+            displayCount: "$displayCount",
+            // 发送成功率 = sent / totalRecords
             sentSuccessRate: {
-              $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: [{ $sum: ["$sent_count", "$delivered_count", "$opened_count"] }, "$total_sent"] }],
-            },
-            tokenInvalidationRate: {
-              $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: ["$failed_count", "$total_sent"] }],
+              $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$sent", "$totalRecords"] }],
             },
+            // 送达率 = delivered / sent
             deliveredRate: {
-              $cond: [{ $eq: [{ $sum: ["$sent_count", "$delivered_count"] }, 0] }, 0, { $divide: ["$delivered_count", { $sum: ["$sent_count", "$delivered_count"] }] }],
+              $cond: [{ $eq: ["$sent", 0] }, 0, { $divide: ["$delivered", "$sent"] }],
+            },
+            // 展示率 = displayCount / delivered
+            displayRate: {
+              $cond: [{ $eq: ["$delivered", 0] }, 0, { $divide: ["$displayCount", "$delivered"] }],
             },
-            openedRate: {
-              $cond: [{ $eq: [{ $sum: ["$delivered_count", "$opened_count"] }, 0] }, 0, { $divide: ["$opened_count", { $sum: ["$delivered_count", "$opened_count"] }] }],
+            // 点击率 = opened / displayCount
+            clickThroughRate: {
+              $cond: [{ $eq: ["$displayCount", 0] }, 0, { $divide: ["$opened", "$displayCount"] }],
+            },
+            // Token 失效率 = failed / totalRecords
+            tokenInvalidationRate: {
+              $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$failed", "$totalRecords"] }],
             },
           },
         },
@@ -299,10 +284,15 @@ export class MessageRecordService {
   public async getStatisticsByStrategy() {
     try {
       const results = await MessageRecord.aggregate([
-        // 1. 根据 strategyId 和 status 进行分组
+        // 1. 根据 strategyId, status, 和 inforeground 进行分组
         {
           $group: {
-            _id: { strategyId: "$strategyId", strategyName: "$strategyName", status: "$status" },
+            _id: {
+              strategyId: "$strategyId",
+              strategyName: "$strategyName",
+              status: "$status",
+              inforeground: "$inforeground",
+            },
             count: { $sum: 1 },
           },
         },
@@ -311,17 +301,34 @@ export class MessageRecordService {
           $group: {
             _id: "$_id.strategyId",
             strategyName: { $first: "$_id.strategyName" },
-            total_sent: { $sum: "$count" },
-            sent_count: { $sum: { $cond: [{ $eq: ["$_id.status", 1] }, "$count", 0] } },
-            delivered_count: {
-              $sum: { $cond: [{ $eq: ["$_id.status", 2] }, "$count", 0] },
+            totalRecords: { $sum: "$count" },
+            // 发送成功数:status >= 1
+            sent: {
+              $sum: { $cond: [{ $gte: ["$_id.status", 1] }, "$count", 0] },
+            },
+            // 送达数:status >= 2
+            delivered: {
+              $sum: { $cond: [{ $gte: ["$_id.status", 2] }, "$count", 0] },
             },
-            opened_count: {
+            // 打开数:status === 3
+            opened: {
               $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] },
             },
-            failed_count: {
+            failed: {
               $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] },
             },
+            // 展示数:status >= 2 并且 inforeground = false
+            displayCount: {
+              $sum: {
+                $cond: [
+                  {
+                    $and: [{ $gte: ["$_id.status", 2] }, { $eq: ["$_id.inforeground", false] }],
+                  },
+                  "$count",
+                  0,
+                ],
+              },
+            },
           },
         },
         // 3. 计算比率并格式化输出
@@ -330,22 +337,31 @@ export class MessageRecordService {
             _id: 0,
             strategyId: "$_id",
             strategyName: "$strategyName",
-            totalSent: "$total_sent",
-            sent: "$sent_count",
-            delivered: "$delivered_count",
-            opened: "$opened_count",
-            failed: "$failed_count",
+            totalRecords: "$totalRecords",
+            sent: "$sent",
+            delivered: "$delivered",
+            opened: "$opened",
+            failed: "$failed",
+            displayCount: "$displayCount",
+            // 发送成功率 = sent / totalRecords
             sentSuccessRate: {
-              $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: [{ $sum: ["$sent_count", "$delivered_count", "$opened_count"] }, "$total_sent"] }],
-            },
-            tokenInvalidationRate: {
-              $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: ["$failed_count", "$total_sent"] }],
+              $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$sent", "$totalRecords"] }],
             },
+            // 送达率 = delivered / sent
             deliveredRate: {
-              $cond: [{ $eq: [{ $sum: ["$sent_count", "$delivered_count"] }, 0] }, 0, { $divide: ["$delivered_count", { $sum: ["$sent_count", "$delivered_count"] }] }],
+              $cond: [{ $eq: ["$sent", 0] }, 0, { $divide: ["$delivered", "$sent"] }],
+            },
+            // 展示率 = displayCount / delivered
+            displayRate: {
+              $cond: [{ $eq: ["$delivered", 0] }, 0, { $divide: ["$displayCount", "$delivered"] }],
             },
-            openedRate: {
-              $cond: [{ $eq: [{ $sum: ["$delivered_count", "$opened_count"] }, 0] }, 0, { $divide: ["$opened_count", { $sum: ["$delivered_count", "$opened_count"] }] }],
+            // 点击率 = opened / displayCount
+            clickThroughRate: {
+              $cond: [{ $eq: ["$displayCount", 0] }, 0, { $divide: ["$opened", "$displayCount"] }],
+            },
+            // Token 失效率 = failed / totalRecords
+            tokenInvalidationRate: {
+              $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$failed", "$totalRecords"] }],
             },
           },
         },
@@ -354,7 +370,6 @@ export class MessageRecordService {
           $sort: { deliveredRate: -1 },
         },
       ]);
-
       return results;
     } catch (error) {
       console.error("Error fetching statistics by strategy:", error);
@@ -368,10 +383,15 @@ export class MessageRecordService {
   public async getStatisticsByTemplate() {
     try {
       const results = await MessageRecord.aggregate([
-        // 1. 根据 templateId 和 status 进行分组
+        // 1. 根据 templateId, status, 和 inforeground 进行分组
         {
           $group: {
-            _id: { templateId: "$templateId", templateName: "$templateName", status: "$status" },
+            _id: {
+              templateId: "$templateId",
+              templateName: "$templateName",
+              status: "$status",
+              inforeground: "$inforeground",
+            },
             count: { $sum: 1 },
           },
         },
@@ -380,17 +400,34 @@ export class MessageRecordService {
           $group: {
             _id: "$_id.templateId",
             templateName: { $first: "$_id.templateName" },
-            total_sent: { $sum: "$count" },
-            sent_count: { $sum: { $cond: [{ $eq: ["$_id.status", 1] }, "$count", 0] } },
-            delivered_count: {
-              $sum: { $cond: [{ $eq: ["$_id.status", 2] }, "$count", 0] },
+            totalRecords: { $sum: "$count" },
+            // 发送成功数:status >= 1
+            sent: {
+              $sum: { $cond: [{ $gte: ["$_id.status", 1] }, "$count", 0] },
+            },
+            // 送达数:status >= 2
+            delivered: {
+              $sum: { $cond: [{ $gte: ["$_id.status", 2] }, "$count", 0] },
             },
-            opened_count: {
+            // 打开数:status === 3
+            opened: {
               $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] },
             },
-            failed_count: {
+            failed: {
               $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] },
             },
+            // 展示数:status >= 2 并且 inforeground = false
+            displayCount: {
+              $sum: {
+                $cond: [
+                  {
+                    $and: [{ $gte: ["$_id.status", 2] }, { $eq: ["$_id.inforeground", false] }],
+                  },
+                  "$count",
+                  0,
+                ],
+              },
+            },
           },
         },
         // 3. 计算比率并格式化输出
@@ -399,22 +436,31 @@ export class MessageRecordService {
             _id: 0,
             templateId: "$_id",
             templateName: "$templateName",
-            totalSent: "$total_sent",
-            sent: "$sent_count",
-            delivered: "$delivered_count",
-            opened: "$opened_count",
-            failed: "$failed_count",
+            totalRecords: "$totalRecords",
+            sent: "$sent",
+            delivered: "$delivered",
+            opened: "$opened",
+            failed: "$failed",
+            displayCount: "$displayCount",
+            // 发送成功率 = sent / totalRecords
             sentSuccessRate: {
-              $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: [{ $sum: ["$sent_count", "$delivered_count", "$opened_count"] }, "$total_sent"] }],
-            },
-            tokenInvalidationRate: {
-              $cond: [{ $eq: ["$total_sent", 0] }, 0, { $divide: ["$failed_count", "$total_sent"] }],
+              $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$sent", "$totalRecords"] }],
             },
+            // 送达率 = delivered / sent
             deliveredRate: {
-              $cond: [{ $eq: [{ $sum: ["$sent_count", "$delivered_count"] }, 0] }, 0, { $divide: ["$delivered_count", { $sum: ["$sent_count", "$delivered_count"] }] }],
+              $cond: [{ $eq: ["$sent", 0] }, 0, { $divide: ["$delivered", "$sent"] }],
+            },
+            // 展示率 = displayCount / delivered
+            displayRate: {
+              $cond: [{ $eq: ["$delivered", 0] }, 0, { $divide: ["$displayCount", "$delivered"] }],
             },
-            openedRate: {
-              $cond: [{ $eq: [{ $sum: ["$delivered_count", "$opened_count"] }, 0] }, 0, { $divide: ["$opened_count", { $sum: ["$delivered_count", "$opened_count"] }] }],
+            // 点击率 = opened / displayCount
+            clickThroughRate: {
+              $cond: [{ $eq: ["$displayCount", 0] }, 0, { $divide: ["$opened", "$displayCount"] }],
+            },
+            // Token 失效率 = failed / totalRecords
+            tokenInvalidationRate: {
+              $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$failed", "$totalRecords"] }],
             },
           },
         },
@@ -423,7 +469,6 @@ export class MessageRecordService {
           $sort: { deliveredRate: -1 },
         },
       ]);
-
       return results;
     } catch (error) {
       console.error("Error fetching statistics by template:", error);
@@ -443,12 +488,13 @@ export class MessageRecordService {
               $dateTrunc: { date: "$actualSendAt", unit: "day", timezone: "America/Los_Angeles" },
             },
             status: "$status",
+            inforeground: "$inforeground",
           },
         },
-        // 2. 根据日期和状态进行分组
+        // 2. 根据日期、状态和 inforeground 进行分组
         {
           $group: {
-            _id: { date: "$date", status: "$status" },
+            _id: { date: "$date", status: "$status", inforeground: "$inforeground" },
             count: { $sum: 1 },
           },
         },
@@ -456,11 +502,34 @@ export class MessageRecordService {
         {
           $group: {
             _id: "$_id.date",
-            totalSent: { $sum: "$count" },
-            sent: { $sum: { $cond: [{ $eq: ["$_id.status", 1] }, "$count", 0] } },
-            delivered: { $sum: { $cond: [{ $eq: ["$_id.status", 2] }, "$count", 0] } },
-            opened: { $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] } },
-            failed: { $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] } },
+            totalRecords: { $sum: "$count" },
+            // 发送成功数:status >= 1
+            sent: {
+              $sum: { $cond: [{ $gte: ["$_id.status", 1] }, "$count", 0] },
+            },
+            // 送达数:status >= 2
+            delivered: {
+              $sum: { $cond: [{ $gte: ["$_id.status", 2] }, "$count", 0] },
+            },
+            // 打开数:status === 3
+            opened: {
+              $sum: { $cond: [{ $eq: ["$_id.status", 3] }, "$count", 0] },
+            },
+            failed: {
+              $sum: { $cond: [{ $eq: ["$_id.status", -1] }, "$count", 0] },
+            },
+            // 展示数:status >= 2 并且 inforeground = false
+            displayCount: {
+              $sum: {
+                $cond: [
+                  {
+                    $and: [{ $gte: ["$_id.status", 2] }, { $eq: ["$_id.inforeground", false] }],
+                  },
+                  "$count",
+                  0,
+                ],
+              },
+            },
           },
         },
         // 4. 计算比率并格式化输出
@@ -468,26 +537,31 @@ export class MessageRecordService {
           $project: {
             _id: 0,
             date: "$_id",
-            totalSent: "$totalSent",
+            totalRecords: "$totalRecords",
             sent: "$sent",
             delivered: "$delivered",
             opened: "$opened",
             failed: "$failed",
-            // Sent success rate = (sent + delivered + opened) / total
+            displayCount: "$displayCount",
+            // 发送成功率 = sent / totalRecords
             sentSuccessRate: {
-              $cond: [{ $eq: ["$totalSent", 0] }, 0, { $divide: [{ $sum: ["$sent", "$delivered", "$opened"] }, "$totalSent"] }],
+              $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$sent", "$totalRecords"] }],
             },
-            // Delivered rate = delivered / (sent + delivered)
+            // 送达率 = delivered / sent
             deliveredRate: {
-              $cond: [{ $eq: [{ $sum: ["$sent", "$delivered"] }, 0] }, 0, { $divide: ["$delivered", { $sum: ["$sent", "$delivered"] }] }],
+              $cond: [{ $eq: ["$sent", 0] }, 0, { $divide: ["$delivered", "$sent"] }],
             },
-            // Opened rate = opened / (delivered + opened)
-            openedRate: {
-              $cond: [{ $eq: [{ $sum: ["$delivered", "$opened"] }, 0] }, 0, { $divide: ["$opened", { $sum: ["$delivered", "$opened"] }] }],
+            // 展示率 = displayCount / delivered
+            displayRate: {
+              $cond: [{ $eq: ["$delivered", 0] }, 0, { $divide: ["$displayCount", "$delivered"] }],
+            },
+            // 点击率 = opened / displayCount
+            clickThroughRate: {
+              $cond: [{ $eq: ["$displayCount", 0] }, 0, { $divide: ["$opened", "$displayCount"] }],
             },
             // Token invalidation rate
             tokenInvalidationRate: {
-              $cond: [{ $eq: ["$totalSent", 0] }, 0, { $divide: ["$failed", "$totalSent"] }],
+              $cond: [{ $eq: ["$totalRecords", 0] }, 0, { $divide: ["$failed", "$totalRecords"] }],
             },
           },
         },
@@ -496,7 +570,6 @@ export class MessageRecordService {
           $sort: { date: 1 },
         },
       ]);
-
       return results;
     } catch (error) {
       console.error("Error fetching daily sent trends:", error);
@@ -504,14 +577,14 @@ export class MessageRecordService {
     }
   }
 
-  // 消息生命周期分析, 利用 plannedSendAt、actualSendAt、deliveredAt 和 openedAt 字段,可以分析消息从计划到被用户打开的整个生命周期。
+  // 消息生命周期分析
   public async getAverageDeliveryTime() {
     try {
       const result = await MessageRecord.aggregate([
-        // 1. 只筛选出已送达的消息(status = 2 或 3
+        // 1. 只筛选出已送达的消息(status >= 2)
         {
           $match: {
-            status: { $in: [2, 3] },
+            status: { $gte: 2 },
             actualSendAt: { $exists: true, $ne: null },
             deliveredAt: { $exists: true, $ne: null },
           },

+ 1 - 1
omsapp/src/app/app.routes.ts

@@ -26,7 +26,7 @@ export const routes: Routes = [
       { path: 'message-record', component: MessageRecordComponent },
       { path: 'message-template', component: MessageTemplateComponent },
       { path: 'message-strategy', component: MessageStrategyComponent },
-      { path: 'message-statistics', component: MessageDashboardComponent },
+      { path: 'message-dashboard', component: MessageDashboardComponent },
     ],
   },
   // 顶级重定向:确保应用启动时重定向到 '/dashboard'

+ 3 - 3
omsapp/src/app/layouts/main-layout.component.ts

@@ -108,9 +108,9 @@ interface TabItem {
                 </li>
                 <li
                   nz-menu-item
-                  [routerLink]="['/message-statistics']"
+                  [routerLink]="['/message-dashboard']"
                   [routerLinkActive]="['ant-menu-item-selected']"
-                  [nzSelected]="activePath === '/message-statistics'"
+                  [nzSelected]="activePath === '/message-dashboard'"
                 >
                   <span nz-icon nzType="line-chart"></span>
                   <span>统计分析</span>
@@ -421,7 +421,7 @@ export class MainLayoutComponent implements OnInit, OnDestroy, AfterViewInit {
     '/message-record': '推送记录',
     '/message-template': '消息模板',
     '/message-strategy': '推送策略',
-    '/message-statistics': '统计分析',
+    '/message-dashboard': '统计分析',
   };
 
   constructor(private router: Router, private authService: AuthService) {}

+ 204 - 8
omsapp/src/app/pages/message-dashboard.component.css

@@ -1,29 +1,225 @@
+/* 基础布局样式 */
 .filter-controls {
   display: flex;
   align-items: center;
   margin-bottom: 16px;
 }
 
+/* 统计卡片样式 */
+nz-card {
+  margin-bottom: 16px;
+  border-radius: 4px;
+  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.03);
+}
+
+nz-card[nzTitle]::before {
+  content: none;
+}
+
+/* 统计数字样式 */
 nz-statistic {
   text-align: center;
 }
 
+.statistic-subtext {
+  font-size: 12px;
+  color: rgba(0, 0, 0, 0.45);
+  text-align: center;
+  margin-top: -8px;
+}
+
+/* 图表容器样式 */
+.chart-container {
+  position: relative;
+  width: 100%;
+  min-height: 400px;
+  margin-top: 8px;
+}
+
+/* 表格样式优化 */
+nz-table {
+  width: 100%;
+  overflow-x: auto;
+  margin-top: 16px;
+}
+
+nz-table th {
+  white-space: nowrap;
+  background-color: #fafafa;
+  font-weight: 500;
+  padding: 12px 16px !important;
+}
+
+nz-table td {
+  white-space: nowrap;
+  padding: 12px 16px !important;
+  transition: background-color 0.3s;
+}
+
+nz-table tr:hover td {
+  background-color: #f5f5f5;
+}
+
+/* 表格链接样式 */
+nz-table a {
+  color: #1890ff;
+  cursor: pointer;
+  text-decoration: none;
+}
+
+nz-table a:hover {
+  text-decoration: underline;
+}
+
+/* 进度条样式 */
 nz-progress {
+  display: inline-block;
+  width: 80px;
   margin-right: 8px;
+  vertical-align: middle;
+}
+
+.progress-container {
+  display: flex;
+  align-items: center;
+}
+
+/* 百分比文本样式 */
+.percentage-text {
   display: inline-block;
-  width: 100px;
+  min-width: 60px;
+  font-size: 12px;
+  color: rgba(0, 0, 0, 0.65);
 }
 
-nz-card {
-  margin-bottom: 16px;
+/* 特殊列样式 */
+.strategy-name-col,
+.template-name-col {
+  min-width: 150px;
+  max-width: 200px;
+  overflow: hidden;
+  text-overflow: ellipsis;
 }
 
-.chart-container {
-  position: relative;
-  height: 100%;
-  width: 100%;
+.display-count-column {
+  color: #faad14;
+  font-weight: 500;
 }
 
-nz-table {
+.display-rate-column {
+  background-color: rgba(250, 173, 20, 0.05);
+}
+
+.click-rate-column {
+  background-color: rgba(114, 46, 209, 0.05);
+}
+
+/* 空状态样式 */
+nz-empty {
+  margin: 40px 0;
+}
+
+/* 标签页样式 */
+nz-tabset {
   margin-top: 16px;
 }
+
+nz-tabs-nav {
+  margin-bottom: 0;
+}
+
+/* 响应式调整 */
+@media (max-width: 1600px) {
+  nz-table {
+    font-size: 13px;
+  }
+
+  nz-table th,
+  nz-table td {
+    padding: 8px 12px !important;
+  }
+
+  .progress-container {
+    flex-direction: column;
+    align-items: flex-start;
+  }
+
+  nz-progress {
+    width: 100%;
+    margin-right: 0;
+    margin-bottom: 4px;
+  }
+
+  .percentage-text {
+    min-width: 100%;
+    text-align: left;
+  }
+}
+
+@media (max-width: 1200px) {
+  nz-table {
+    font-size: 12px;
+  }
+
+  nz-progress {
+    width: 60px;
+  }
+
+  .statistic-subtext {
+    font-size: 11px;
+  }
+}
+
+@media (max-width: 768px) {
+  .chart-container {
+    min-height: 300px;
+  }
+
+  nz-table {
+    font-size: 11px;
+  }
+
+  nz-table td,
+  nz-table th {
+    padding: 8px !important;
+  }
+
+  .filter-controls {
+    flex-direction: column;
+    align-items: flex-start;
+  }
+
+  .filter-controls nz-range-picker {
+    width: 100%;
+    margin-right: 0;
+    margin-bottom: 8px;
+  }
+
+  nz-statistic {
+    margin-bottom: 8px;
+  }
+}
+
+/* 状态颜色 */
+.status-success {
+  color: #52c41a;
+}
+
+.status-warning {
+  color: #faad14;
+}
+
+.status-error {
+  color: #ff4d4f;
+}
+
+/* 加载动画 */
+nz-spin {
+  display: block;
+  min-height: 200px;
+}
+
+/* 卡片标题样式 */
+nz-card[nzTitle] {
+  border-top: 3px solid #1890ff;
+}

+ 199 - 98
omsapp/src/app/pages/message-dashboard.component.html

@@ -4,8 +4,7 @@
       [(ngModel)]="dateRange"
       (ngModelChange)="refreshData()"
       style="width: 300px; margin-right: 16px"
-    >
-    </nz-range-picker>
+    ></nz-range-picker>
     <button
       nz-button
       nzType="primary"
@@ -20,64 +19,90 @@
     <!-- 整体统计卡片 -->
     <nz-card nzTitle="整体统计" style="margin-top: 16px">
       <div nz-row [nzGutter]="16" *ngIf="overallStats">
-        <div nz-col [nzSpan]="6">
+        <div nz-col [nzSpan]="4">
           <nz-statistic
             nzTitle="总发送量"
             [nzValue]="overallStats.totalRecords || 0"
-          >
-          </nz-statistic>
+          ></nz-statistic>
+        </div>
+
+        <div nz-col [nzSpan]="4">
+          <nz-statistic
+            nzTitle="发送成功率"
+            [nzValue]="formatPercentage(overallStats.sentSuccessRate || 0)"
+          ></nz-statistic>
+          <div class="statistic-subtext">
+            成功数: {{ overallStats.sent || 0 }}
+          </div>
         </div>
-        <div nz-col [nzSpan]="6">
+
+        <div nz-col [nzSpan]="4">
           <nz-statistic
             nzTitle="送达率"
             [nzValue]="formatPercentage(overallStats.deliveredRate || 0)"
-          >
-          </nz-statistic>
+          ></nz-statistic>
+          <div class="statistic-subtext">
+            送达数: {{ overallStats.delivered || 0 }}
+          </div>
         </div>
-        <div nz-col [nzSpan]="6">
+
+        <div nz-col [nzSpan]="4">
           <nz-statistic
-            nzTitle="打开率"
-            [nzValue]="formatPercentage(overallStats.openedRate || 0)"
-          >
-          </nz-statistic>
+            nzTitle="展示率"
+            [nzValue]="formatPercentage(overallStats.displayRate || 0)"
+          ></nz-statistic>
+          <div class="statistic-subtext">
+            展示数: {{ overallStats.displayCount || 0 }}
+          </div>
         </div>
-        <div nz-col [nzSpan]="6">
+
+        <div nz-col [nzSpan]="4">
+          <nz-statistic
+            nzTitle="点击率"
+            [nzValue]="formatPercentage(overallStats.clickThroughRate || 0)"
+          ></nz-statistic>
+        </div>
+
+        <div nz-col [nzSpan]="4">
           <nz-statistic
             nzTitle="失败率"
             [nzValue]="
               formatPercentage(overallStats.tokenInvalidationRate || 0)
             "
-          >
-          </nz-statistic>
+          ></nz-statistic>
+          <div class="statistic-subtext">
+            失败数: {{ overallStats.failed || 0 }}
+          </div>
         </div>
       </div>
     </nz-card>
 
     <!-- 图表区域 -->
     <div nz-row [nzGutter]="16" style="margin-top: 16px">
-      <div nz-col [nzSpan]="12">
-        <nz-card nzTitle="每日消息趋势">
-          <div style="height: 300px">
+      <div nz-col [nzSpan]="24">
+        <nz-card nzTitle="每日消息量统计">
+          <div class="chart-container">
             <canvas
               baseChart
-              [type]="'line'"
-              [data]="lineChartData"
-              [options]="chartOptions"
-            >
-            </canvas>
+              [type]="'bar'"
+              [data]="combinedChartData"
+              [options]="combinedChartOptions"
+            ></canvas>
           </div>
         </nz-card>
       </div>
-      <div nz-col [nzSpan]="12">
-        <nz-card nzTitle="每日送达量">
-          <div style="height: 300px">
+    </div>
+
+    <div nz-row [nzGutter]="16" style="margin-top: 16px">
+      <div nz-col [nzSpan]="24">
+        <nz-card nzTitle="每日成功率趋势">
+          <div class="chart-container">
             <canvas
               baseChart
-              [type]="'bar'"
-              [data]="barChartData"
-              [options]="chartOptions"
-            >
-            </canvas>
+              [type]="'line'"
+              [data]="rateChartData"
+              [options]="combinedChartOptions"
+            ></canvas>
           </div>
         </nz-card>
       </div>
@@ -98,51 +123,89 @@
             <tr>
               <th>策略名称</th>
               <th>总发送量</th>
+              <th>成功数</th>
+              <th>送达数</th>
+              <th>打开数</th>
+              <th>展示数</th>
+              <th>失败数</th>
               <th>送达率</th>
-              <th>打开率</th>
+              <th>展示率</th>
+              <th>点击率</th>
               <th>失败率</th>
-              <th>操作</th>
             </tr>
           </thead>
           <tbody>
             <tr *ngFor="let item of strategyTable.data">
-              <td>{{ item.strategyName || "-" }}</td>
-              <td>{{ item.totalSent || 0 }}</td>
-              <td>
-                <nz-progress
-                  [nzPercent]="(preciseRound(item.deliveredRate, 2) || 0) * 100"
-                  nzSize="small"
-                  nzStatus="normal"
+              <td class="strategy-name-col">
+                <a
+                  (click)="navigateToStrategy(item.strategyName)"
+                  *ngIf="item.strategyName"
                 >
-                </nz-progress>
-                {{ formatPercentage(item.deliveredRate || 0) }}
+                  {{ item.strategyName || "-" }}
+                </a>
+                <span *ngIf="!item.strategyName">-</span>
               </td>
+              <td>{{ item.totalRecords || 0 }}</td>
+              <td>{{ item.sent || 0 }}</td>
+              <td>{{ item.delivered || 0 }}</td>
+              <td>{{ item.opened || 0 }}</td>
+              <td class="display-count-column">{{ item.displayCount || 0 }}</td>
+              <td>{{ item.failed || 0 }}</td>
               <td>
-                <nz-progress
-                  [nzPercent]="(preciseRound(item.openedRate, 2) || 0) * 100"
-                  nzSize="small"
-                  nzStatus="active"
-                >
-                </nz-progress>
-                {{ formatPercentage(item.openedRate || 0) }}
+                <div class="progress-container">
+                  <nz-progress
+                    [nzPercent]="
+                      formatPercentageToNumber(item.deliveredRate || 0)
+                    "
+                    nzSize="small"
+                    nzStatus="normal"
+                  ></nz-progress>
+                  <!-- <span class="percentage-text">{{
+                    formatPercentage(item.deliveredRate || 0)
+                  }}</span> -->
+                </div>
               </td>
-              <td>
-                <nz-progress
-                  [nzPercent]="
-                    (preciseRound(item.tokenInvalidationRate, 2) || 0) * 100
-                  "
-                  nzSize="small"
-                  nzStatus="exception"
-                >
-                </nz-progress>
-                {{ formatPercentage(item.tokenInvalidationRate || 0) }}
+              <td class="display-rate-column">
+                <div class="progress-container">
+                  <nz-progress
+                    [nzPercent]="
+                      formatPercentageToNumber(item.displayRate || 0)
+                    "
+                    nzSize="small"
+                    nzStatus="active"
+                  ></nz-progress>
+                  <!-- <span class="percentage-text">{{
+                    formatPercentage(item.displayRate || 0)
+                  }}</span> -->
+                </div>
+              </td>
+              <td class="click-rate-column">
+                <div class="progress-container">
+                  <nz-progress
+                    [nzPercent]="
+                      formatPercentageToNumber(item.clickThroughRate || 0)
+                    "
+                    nzSize="small"
+                    nzStatus="active"
+                  ></nz-progress>
+                  <!-- <span class="percentage-text">{{
+                    formatPercentage(item.clickThroughRate || 0)
+                  }}</span> -->
+                </div>
               </td>
               <td>
-                <a
-                  (click)="navigateToStrategy(item.strategyName)"
-                  *ngIf="item.strategyId"
-                  >查看详情</a
-                >
+                <div class="progress-container">
+                  <nz-progress
+                    [nzPercent]="
+                      formatPercentageToNumber(item.tokenInvalidationRate || 0)
+                    "
+                    nzSize="small"
+                    nzStatus="exception"
+                  ></nz-progress>
+                  <span class="percentage-text">{{
+                    formatPercentage(item.tokenInvalidationRate || 0)
+                  }}</span>
+                </div>
               </td>
             </tr>
           </tbody>
@@ -163,51 +226,89 @@
             <tr>
               <th>模板名称</th>
               <th>总发送量</th>
+              <th>成功数</th>
+              <th>送达数</th>
+              <th>打开数</th>
+              <th>展示数</th>
+              <th>失败数</th>
               <th>送达率</th>
-              <th>打开率</th>
+              <th>展示率</th>
+              <th>点击率</th>
               <th>失败率</th>
-              <th>操作</th>
             </tr>
           </thead>
           <tbody>
             <tr *ngFor="let item of templateTable.data">
-              <td>{{ item.templateName || "-" }}</td>
-              <td>{{ item.totalSent || 0 }}</td>
-              <td>
-                <nz-progress
-                  [nzPercent]="(preciseRound(item.deliveredRate, 2) || 0) * 100"
-                  nzSize="small"
-                  nzStatus="normal"
+              <td class="template-name-col">
+                <a
+                  (click)="navigateToTemplate(item.templateName)"
+                  *ngIf="item.templateName"
                 >
-                </nz-progress>
-                {{ formatPercentage(item.deliveredRate || 0) }}
+                  {{ item.templateName || "-" }}
+                </a>
+                <span *ngIf="!item.templateName">-</span>
               </td>
+              <td>{{ item.totalRecords || 0 }}</td>
+              <td>{{ item.sent || 0 }}</td>
+              <td>{{ item.delivered || 0 }}</td>
+              <td>{{ item.opened || 0 }}</td>
+              <td class="display-count-column">{{ item.displayCount || 0 }}</td>
+              <td>{{ item.failed || 0 }}</td>
               <td>
-                <nz-progress
-                  [nzPercent]="(preciseRound(item.openedRate, 2) || 0) * 100"
-                  nzSize="small"
-                  nzStatus="active"
-                >
-                </nz-progress>
-                {{ formatPercentage(item.openedRate || 0) }}
+                <div class="progress-container">
+                  <nz-progress
+                    [nzPercent]="
+                      formatPercentageToNumber(item.deliveredRate || 0)
+                    "
+                    nzSize="small"
+                    nzStatus="normal"
+                  ></nz-progress>
+                  <!-- <span class="percentage-text">{{
+                    formatPercentage(item.deliveredRate || 0)
+                  }}</span> -->
+                </div>
               </td>
-              <td>
-                <nz-progress
-                  [nzPercent]="
-                    (preciseRound(item.tokenInvalidationRate, 2) || 0) * 100
-                  "
-                  nzSize="small"
-                  nzStatus="exception"
-                >
-                </nz-progress>
-                {{ formatPercentage(item.tokenInvalidationRate || 0) }}
+              <td class="display-rate-column">
+                <div class="progress-container">
+                  <nz-progress
+                    [nzPercent]="
+                      formatPercentageToNumber(item.displayRate || 0)
+                    "
+                    nzSize="small"
+                    nzStatus="active"
+                  ></nz-progress>
+                  <!-- <span class="percentage-text">{{
+                    formatPercentage(item.displayRate || 0)
+                  }}</span> -->
+                </div>
+              </td>
+              <td class="click-rate-column">
+                <div class="progress-container">
+                  <nz-progress
+                    [nzPercent]="
+                      formatPercentageToNumber(item.clickThroughRate || 0)
+                    "
+                    nzSize="small"
+                    nzStatus="active"
+                  ></nz-progress>
+                  <!-- <span class="percentage-text">{{
+                    formatPercentage(item.clickThroughRate || 0)
+                  }}</span> -->
+                </div>
               </td>
               <td>
-                <a
-                  (click)="navigateToTemplate(item.templateName)"
-                  *ngIf="item.templateId"
-                  >查看详情</a
-                >
+                <div class="progress-container">
+                  <nz-progress
+                    [nzPercent]="
+                      formatPercentageToNumber(item.tokenInvalidationRate || 0)
+                    "
+                    nzSize="small"
+                    nzStatus="exception"
+                  ></nz-progress>
+                  <!-- <span class="percentage-text">{{
+                    formatPercentage(item.tokenInvalidationRate || 0)
+                  }}</span> -->
+                </div>
               </td>
             </tr>
           </tbody>

+ 158 - 67
omsapp/src/app/pages/message-dashboard.component.ts

@@ -64,47 +64,136 @@ export class MessageDashboardComponent implements OnInit {
   isLoading = false;
   overallStats: any = null;
   strategyStats: any[] = [];
-  templateStats: any[] = []; // 新增模板统计
+  templateStats: any[] = [];
   dailyTrends: any[] = [];
   avgDeliveryTime: any = null;
-  activeTab: number = 0; // 当前激活的标签页
+  activeTab: number = 0;
 
   // 日期范围
   dateRange: Date[] = [];
 
-  // 图表配置
-  public lineChartData: ChartConfiguration<'line'>['data'] = {
+  // 组合图表配置
+  public combinedChartData: ChartConfiguration<'bar'>['data'] = {
     labels: [],
     datasets: [
       {
+        label: '总发送量',
         data: [],
-        label: '消息趋势',
-        borderColor: '#1890ff',
-        backgroundColor: 'rgba(24, 144, 255, 0.2)',
-        tension: 0.4,
-        fill: true,
+        backgroundColor: '#1890ff',
+        yAxisID: 'y',
+      },
+      {
+        label: '成功发送',
+        data: [],
+        backgroundColor: '#52c41a',
+        yAxisID: 'y',
+      },
+      {
+        label: '已送达',
+        data: [],
+        backgroundColor: '#13c2c2',
+        yAxisID: 'y',
+      },
+      {
+        label: '已打开',
+        data: [],
+        backgroundColor: '#722ed1',
+        yAxisID: 'y',
+      },
+      {
+        label: '展示数',
+        data: [],
+        backgroundColor: '#faad14',
+        yAxisID: 'y',
+      },
+      {
+        label: '失败数',
+        data: [],
+        backgroundColor: '#f5222d',
+        yAxisID: 'y',
       },
     ],
   };
 
-  public barChartData: ChartConfiguration<'bar'>['data'] = {
+  public rateChartData: ChartConfiguration<'line'>['data'] = {
     labels: [],
     datasets: [
       {
+        label: '发送成功率',
         data: [],
-        label: '消息量',
-        backgroundColor: '#52c41a',
+        borderColor: '#1890ff',
+        backgroundColor: 'rgba(24, 144, 255, 0.1)',
+        yAxisID: 'y1',
+        tension: 0.3,
+        fill: true,
+      },
+      {
+        label: '送达率',
+        data: [],
+        borderColor: '#52c41a',
+        backgroundColor: 'rgba(82, 196, 26, 0.1)',
+        yAxisID: 'y1',
+        tension: 0.3,
+        fill: true,
+      },
+      {
+        label: '展示率',
+        data: [],
+        borderColor: '#faad14',
+        backgroundColor: 'rgba(250, 173, 20, 0.1)',
+        yAxisID: 'y1',
+        tension: 0.3,
+        fill: true,
+      },
+      {
+        label: '点击率',
+        data: [],
+        borderColor: '#722ed1',
+        backgroundColor: 'rgba(114, 46, 209, 0.1)',
+        yAxisID: 'y1',
+        tension: 0.3,
+        fill: true,
       },
     ],
   };
 
-  public chartOptions: ChartOptions<'line' | 'bar'> = {
+  public combinedChartOptions: ChartOptions<'bar' | 'line'> = {
     responsive: true,
     maintainAspectRatio: false,
+    plugins: {
+      tooltip: {
+        mode: 'index',
+        intersect: false,
+      },
+      legend: {
+        position: 'top',
+      },
+    },
     scales: {
       y: {
+        type: 'linear',
+        display: true,
+        position: 'left',
+        title: {
+          display: true,
+          text: '消息数量',
+        },
         beginAtZero: true,
       },
+      y1: {
+        type: 'linear',
+        display: true,
+        position: 'right',
+        title: {
+          display: true,
+          text: '百分比(%)',
+        },
+        min: 0,
+        max: 100,
+        grid: {
+          drawOnChartArea: false,
+        },
+      },
     },
   };
 
@@ -117,51 +206,20 @@ export class MessageDashboardComponent implements OnInit {
   }
 
   ngOnInit(): void {
-    this.initCharts();
     this.loadAllStatistics();
   }
 
-  private initCharts(): void {
-    this.lineChartData = {
-      labels: [],
-      datasets: [
-        {
-          data: [],
-          label: '消息趋势',
-          borderColor: '#1890ff',
-          backgroundColor: 'rgba(24, 144, 255, 0.2)',
-          tension: 0.4,
-          fill: true,
-        },
-      ],
-    };
-
-    this.barChartData = {
-      labels: [],
-      datasets: [
-        {
-          data: [],
-          label: '消息量',
-          backgroundColor: '#52c41a',
-        },
-      ],
-    };
-  }
-
   loadAllStatistics(): void {
     this.isLoading = true;
 
     Promise.all([
       this.loadOverallStatistics(),
       this.loadStrategyStatistics(),
-      this.loadTemplateStatistics(), // 新增模板统计加载
+      this.loadTemplateStatistics(),
       this.loadDailyTrends(),
       this.loadAvgDeliveryTime(),
     ]).finally(() => {
       this.isLoading = false;
-      if (this.dailyTrends.length === 0) {
-        this.initCharts();
-      }
     });
   }
 
@@ -211,23 +269,58 @@ export class MessageDashboardComponent implements OnInit {
       .then((data: any) => {
         this.dailyTrends = data?.data || [];
 
-        // 更新图表数据
-        this.lineChartData = {
-          labels: this.dailyTrends.map((t) => t.date),
+        // 更新组合图表数据
+        this.combinedChartData = {
+          labels: this.dailyTrends.map((t) => this.formatDate(t.date)),
           datasets: [
             {
-              ...this.lineChartData.datasets[0],
-              data: this.dailyTrends.map((t) => t.totalSent),
+              ...this.combinedChartData.datasets[0],
+              data: this.dailyTrends.map((t) => t.totalRecords || 0),
+            },
+            {
+              ...this.combinedChartData.datasets[1],
+              data: this.dailyTrends.map((t) => t.sent || 0),
+            },
+            {
+              ...this.combinedChartData.datasets[2],
+              data: this.dailyTrends.map((t) => t.delivered || 0),
+            },
+            {
+              ...this.combinedChartData.datasets[3],
+              data: this.dailyTrends.map((t) => t.opened || 0),
+            },
+            {
+              ...this.combinedChartData.datasets[4],
+              data: this.dailyTrends.map((t) => t.displayCount || 0),
+            },
+            {
+              ...this.combinedChartData.datasets[5],
+              data: this.dailyTrends.map((t) => t.failed || 0),
             },
           ],
         };
 
-        this.barChartData = {
-          labels: this.dailyTrends.map((t) => t.date),
+        // 更新比率图表数据
+        this.rateChartData = {
+          labels: this.dailyTrends.map((t) => this.formatDate(t.date)),
           datasets: [
             {
-              ...this.barChartData.datasets[0],
-              data: this.dailyTrends.map((t) => t.delivered),
+              ...this.rateChartData.datasets[0],
+              data: this.dailyTrends.map((t) => (t.sentSuccessRate || 0) * 100),
+            },
+            {
+              ...this.rateChartData.datasets[1],
+              data: this.dailyTrends.map((t) => (t.deliveredRate || 0) * 100),
+            },
+            {
+              ...this.rateChartData.datasets[2],
+              data: this.dailyTrends.map((t) => (t.displayRate || 0) * 100),
+            },
+            {
+              ...this.rateChartData.datasets[3],
+              data: this.dailyTrends.map(
+                (t) => (t.clickThroughRate || 0) * 100
+              ),
             },
           ],
         };
@@ -257,7 +350,7 @@ export class MessageDashboardComponent implements OnInit {
 
   navigateToStrategy(strategyName: string): void {
     this.router.navigate(['/message-strategy'], {
-      queryParams: { templateName: strategyName },
+      queryParams: { strategyName: strategyName },
     });
   }
 
@@ -271,6 +364,10 @@ export class MessageDashboardComponent implements OnInit {
     return (value * 100).toFixed(2) + '%';
   }
 
+  formatPercentageToNumber(value: number): number {
+    return Number((value * 100).toFixed(2));
+  }
+
   formatSeconds(seconds: number): string {
     if (seconds < 60) {
       return seconds.toFixed(2) + '秒';
@@ -279,20 +376,14 @@ export class MessageDashboardComponent implements OnInit {
     }
   }
 
-  /**
-   * 精准四舍五入
-   * @param {number} num - 需要处理的数字
-   * @param {number} decimalPlaces - 保留的小数位数
-   * @returns {number} 四舍五入后的结果
-   */
-  preciseRound(num: number, decimalPlaces: number) {
-    // 处理小数位数为0的情况(直接用 Math.round)
+  preciseRound(num: number, decimalPlaces: number): number {
     if (decimalPlaces === 0) return Math.round(num);
-
-    // 计算放大倍数(10的decimalPlaces次方)
     const multiplier = Math.pow(10, decimalPlaces);
-
-    // 放大 → 四舍五入 → 缩小(避免浮点数精度问题,用 Number() 确保类型)
     return Number(Math.round(num * multiplier) / multiplier);
   }
+
+  private formatDate(date: string | null): string {
+    if (!date) return '未知日期';
+    return new Date(date).toLocaleDateString();
+  }
 }

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است