Forráskód Böngészése

add cc for message record

guoziyun 9 hónapja
szülő
commit
3f13ce0147

+ 4 - 2
oms/dist/services/cron-jobs/active-user-daily-notify.js

@@ -96,13 +96,14 @@ function isTokenInvalidationError(error) {
  * 发送并记录FCM消息。
  * 此函数现在将首先创建数据库记录,然后使用该记录的 _id 作为 msgid 进行发送。
  * @param uid 用户ID
+ * @param cc 用户国家代码
  * @param fcmToken 用户的FCM Token
  * @param template 消息模板
  * @param messageData 消息数据
  * @param strategyId 消息策略ID
  * @param strategyName 消息策略名称
  */
-const sendAndRecordMessage = async (uid, fcmToken, template, messageData, strategyId, strategyName) => {
+const sendAndRecordMessage = async (uid, cc, fcmToken, template, messageData, strategyId, strategyName) => {
     let messageRecord = null;
     let fcmReceipt = null;
     let messageStatus = 0;
@@ -111,6 +112,7 @@ const sendAndRecordMessage = async (uid, fcmToken, template, messageData, strate
         // 1. 先创建 MessageRecord 记录,状态为 0 (未发送)
         messageRecord = await messageRecordModel_1.MessageRecord.create({
             uid: uid,
+            cc: cc,
             templateId: template._id,
             templateName: template.templateName,
             strategyId: strategyId,
@@ -233,7 +235,7 @@ async function run() {
             data1.bigger = "true";
             data1.action = "go/art";
             data1.param = artwork1Id;
-            await sendAndRecordMessage(user.uid, fcmToken, messageData.template1, data1, strategy._id, strategy.name);
+            await sendAndRecordMessage(user.uid, user.cc, fcmToken, messageData.template1, data1, strategy._id, strategy.name);
         }
         console.log("第一批消息发送完成。");
         // 返回一个 Promise,该 Promise 将在 30 分钟后执行并完成所有后续操作

+ 5 - 2
oms/dist/services/cron-jobs/fcm-notify.js

@@ -96,13 +96,14 @@ function isTokenInvalidationError(error) {
  * 发送即时消息并记录。
  * 此函数将创建数据库记录并立即调用FCM API发送。
  * @param uid 用户ID
+ * @param cc 用户国家代码
  * @param fcmToken 用户的FCM Token
  * @param template 消息模板
  * @param messageData 消息数据
  * @param strategyId 消息策略ID
  * @param strategyName 消息策略名称
  */
-const sendImmediateMessageAndRecord = async (uid, fcmToken, template, messageData, strategyId, strategyName) => {
+const sendImmediateMessageAndRecord = async (uid, cc, fcmToken, template, messageData, strategyId, strategyName) => {
     let messageRecord = null;
     let fcmReceipt = null;
     let messageStatus = 0;
@@ -110,6 +111,7 @@ const sendImmediateMessageAndRecord = async (uid, fcmToken, template, messageDat
     try {
         messageRecord = await messageRecordModel_1.MessageRecord.create({
             uid: uid,
+            cc: cc,
             templateId: template._id,
             templateName: template.templateName,
             strategyId: strategyId,
@@ -175,6 +177,7 @@ const createScheduledMessageRecord = async (user, template, messageData, strateg
     try {
         await messageRecordModel_1.MessageRecord.create({
             uid: user.uid,
+            cc: user.cc,
             templateId: template._id,
             templateName: template.templateName,
             strategyId: strategyId,
@@ -259,7 +262,7 @@ async function run() {
             data.bigger = "true";
             data.action = "go/art";
             data.param = artworkId;
-            await sendImmediateMessageAndRecord(user.uid, fcmToken, template, data, immediateStrategy._id, immediateStrategy.name);
+            await sendImmediateMessageAndRecord(user.uid, user.cc, fcmToken, template, data, immediateStrategy._id, immediateStrategy.name);
         }
         console.log("即时发送组处理完成。");
         // 5. 创建第二批消息记录 (定时发送组)

+ 0 - 15
oms/dist/src/controllers/messageRecordController.js

@@ -253,21 +253,6 @@ class MessageRecordController {
                 return res.status(500).json({ success: false, message: "Server error", error: error.message });
             }
         };
-        /**
-         * @route GET /api/message/statistics/avg-delivery-time
-         * @desc Retrieves average message delivery time
-         * @access Private
-         */
-        this.getAverageDeliveryTime = async (req, res) => {
-            try {
-                const stats = await this.messageRecordService.getAverageDeliveryTime();
-                return res.status(200).json({ success: true, data: stats });
-            }
-            catch (error) {
-                console.error("Error fetching average delivery time:", error);
-                return res.status(500).json({ success: false, message: "Server error", error: error.message });
-            }
-        };
         this.messageRecordService = new messageRecordService_1.MessageRecordService();
     }
 }

+ 2 - 0
oms/dist/src/controllers/userController.js

@@ -243,6 +243,7 @@ class UserController {
             // 3. 先创建 MessageRecord 记录
             const messageRecord = new messageRecordModel_1.MessageRecord({
                 uid,
+                cc: user.cc,
                 title,
                 content,
                 image,
@@ -350,6 +351,7 @@ class UserController {
                 // Create a MessageRecord document before sending.
                 const messageRecord = new messageRecordModel_1.MessageRecord({
                     uid,
+                    cc: user.cc,
                     title,
                     content,
                     image,

+ 6 - 0
oms/dist/src/models/messageRecordModel.js

@@ -58,6 +58,7 @@ const messageRecordSchema = new mongoose_1.Schema({
     // 图片url, 非必须
     image: {
         type: String,
+        index: true,
     },
     // 消息通知的消息是否点击展开查看大图。没有图片的情况下一般就设置成false
     bigger: {
@@ -76,6 +77,11 @@ const messageRecordSchema = new mongoose_1.Schema({
     extend: {
         type: String,
     },
+    // 新增字段:国家代码
+    cc: {
+        type: String,
+        index: true,
+    },
     // 0-未发送;1-发送成功;2-已送达;3-已打开;-1-发送失败
     status: {
         type: Number,

+ 0 - 1
oms/dist/src/routes/apiRoutes.js

@@ -25,7 +25,6 @@ router.get("/message/statistics/by-activity", messageRecordController_1.default.
 router.get("/message/statistics/by-strategy", messageRecordController_1.default.getStatisticsByStrategy);
 router.get("/message/statistics/by-template", messageRecordController_1.default.getStatisticsByTemplate);
 router.get("/message/statistics/daily-trends", messageRecordController_1.default.getDailySentTrends);
-router.get("/message/statistics/avg-delivery-time", messageRecordController_1.default.getAverageDeliveryTime);
 // 应用认证中间件,保护所有下面的路由
 router.use(authMiddleware_1.authMiddleware);
 // User routes

+ 5 - 3
oms/dist/src/scripts/active-user-daily-notify.js

@@ -136,13 +136,14 @@ function isTokenInvalidationError(error) {
  * 发送并记录FCM消息。
  * 此函数现在将首先创建数据库记录,然后使用该记录的 _id 作为 msgid 进行发送。
  * @param uid 用户ID
+ * @param cc 用户国家代码
  * @param fcmToken 用户的FCM Token
  * @param template 消息模板
  * @param messageData 消息数据
  * @param strategyId 消息策略ID
  * @param strategyName 消息策略名称
  */
-const sendAndRecordMessage = async (uid, fcmToken, template, messageData, strategyId, strategyName) => {
+const sendAndRecordMessage = async (uid, cc, fcmToken, template, messageData, strategyId, strategyName) => {
     let messageRecord = null;
     let fcmReceipt = null;
     let messageStatus = 0;
@@ -151,6 +152,7 @@ const sendAndRecordMessage = async (uid, fcmToken, template, messageData, strate
         // 1. 先创建 MessageRecord 记录,状态为 0 (未发送)
         messageRecord = await messageRecordModel_1.MessageRecord.create({
             uid: uid,
+            cc: cc,
             templateId: template._id,
             templateName: template.templateName,
             strategyId: strategyId,
@@ -283,7 +285,7 @@ async function run() {
         //   data1.bigger = "true";
         //   data1.action = "go/art";
         //   data1.param = artwork1Id;
-        //   await sendAndRecordMessage(user.uid, fcmToken, messageData.template1, data1, strategy._id, strategy.name);
+        //   await sendAndRecordMessage(user.uid, user.cc, fcmToken, messageData.template1, data1, strategy._id, strategy.name);
         // }
         console.log("第一批消息发送完成。");
         // 返回一个 Promise,该 Promise 将在 30 分钟后执行并完成所有后续操作
@@ -300,7 +302,7 @@ async function run() {
         //       data2.bigger = "true";
         //       data2.action = "go/art";
         //       data2.param = artwork2Id;
-        //       await sendAndRecordMessage(user.uid, fcmToken, messageData.template2, data2, strategy._id, strategy.name);
+        //       await sendAndRecordMessage(user.uid, user.cc, fcmToken, messageData.template2, data2, strategy._id, strategy.name);
         //     }
         //     console.log("第二批消息发送完成。");
         //     // 所有任务完成后,安全地断开数据库连接

+ 52 - 0
oms/dist/src/scripts/backfillCc.js

@@ -0,0 +1,52 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const messageRecordModel_1 = require("../models/messageRecordModel");
+const userModel_1 = require("../models/userModel");
+const database_1 = require("../database");
+/**
+ * 这是一个用于回填 MessageRecord 表中 cc 字段的脚本。
+ * 它会从 User 表中查找每个 uid 对应的 cc 值,并更新 MessageRecord。
+ */
+const backfillCc = async () => {
+    console.log("[Backfill Script] 开始连接数据库...");
+    await (0, database_1.connectToDatabase)();
+    try {
+        // 仅查询那些缺少 cc 字段的 MessageRecord 文档,以提高效率。
+        // 这也确保了脚本的幂等性,可以安全地多次运行。
+        const recordsToUpdate = messageRecordModel_1.MessageRecord.find({ cc: { $exists: false } }).cursor();
+        console.log("[Backfill Script] 找到需要回填的记录。开始处理...");
+        let count = 0;
+        // 使用游标(cursor)逐个处理文档,避免一次性加载大量数据到内存中。
+        for await (const record of recordsToUpdate) {
+            count++;
+            console.log(`[Backfill Script] 正在处理第 ${count} 条记录, _id: ${record._id}`);
+            // 从用户表中查找对应的 cc 字段,仅投影需要的字段以优化查询性能。
+            const user = await userModel_1.User.findOne({ uid: record.uid }, { cc: 1 }).lean();
+            if (user && user.cc) {
+                // 如果找到用户和 cc 字段,则更新 MessageRecord。
+                await messageRecordModel_1.MessageRecord.updateOne({ _id: record._id }, { $set: { cc: user.cc } });
+                console.log(`[Backfill Script] 成功为记录 ${record._id} 回填了 cc 字段: ${user.cc}`);
+            }
+            else {
+                // 如果用户或 cc 字段未找到,打印警告信息。
+                console.warn(`[Backfill Script] 未找到用户 ${record.uid} 或其 cc 字段,跳过此记录。`);
+            }
+        }
+        console.log(`[Backfill Script] 脚本执行完毕。总共处理了 ${count} 条记录。`);
+    }
+    catch (error) {
+        console.error("[Backfill Script] 脚本执行过程中发生错误:", error);
+    }
+    finally {
+        console.log("[Backfill Script] 断开数据库连接...");
+        await (0, database_1.disconnectFromDatabase)();
+        process.exit(0);
+    }
+};
+// 确保脚本被直接运行时才执行 backfillCc 函数。
+if (require.main === module) {
+    backfillCc().catch((err) => {
+        console.error("脚本启动失败:", err);
+        process.exit(1);
+    });
+}

+ 0 - 44
oms/dist/src/services/messageRecordService.js

@@ -561,49 +561,5 @@ class MessageRecordService {
             return [];
         }
     }
-    // 消息生命周期分析
-    async getAverageDeliveryTime() {
-        try {
-            const result = await messageRecordModel_1.MessageRecord.aggregate([
-                // 1. 只筛选出已送达的消息(status >= 2)
-                {
-                    $match: {
-                        status: { $gte: 2 },
-                        actualSendAt: { $exists: true, $ne: null },
-                        deliveredAt: { $exists: true, $ne: null },
-                    },
-                },
-                // 2. 计算每条消息的发送到送达的时间差(毫秒)
-                {
-                    $addFields: {
-                        time_to_deliver: {
-                            $subtract: ["$deliveredAt", "$actualSendAt"],
-                        },
-                    },
-                },
-                // 3. 计算平均时间
-                {
-                    $group: {
-                        _id: null,
-                        avg_time_to_deliver_ms: { $avg: "$time_to_deliver" },
-                    },
-                },
-                // 4. 转换成秒或分钟以方便阅读
-                {
-                    $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;
-        }
-    }
 }
 exports.MessageRecordService = MessageRecordService;

+ 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-Z7J4MUAA.js" type="module"></script></body>
+  <script src="polyfills-B6TNHZQ6.js" type="module"></script><script src="main-MTEOIJPW.js" type="module"></script></body>
 </html>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
oms/public/app/main-MTEOIJPW.js


+ 12 - 2
oms/services/cron-jobs/active-user-daily-notify.ts

@@ -101,13 +101,22 @@ function isTokenInvalidationError(error: any): boolean {
  * 发送并记录FCM消息。
  * 此函数现在将首先创建数据库记录,然后使用该记录的 _id 作为 msgid 进行发送。
  * @param uid 用户ID
+ * @param cc 用户国家代码
  * @param fcmToken 用户的FCM Token
  * @param template 消息模板
  * @param messageData 消息数据
  * @param strategyId 消息策略ID
  * @param strategyName 消息策略名称
  */
-const sendAndRecordMessage = async (uid: string, fcmToken: string, template: IMessageTemplate, messageData: { [key: string]: string }, strategyId: mongoose.Types.ObjectId, strategyName: string) => {
+const sendAndRecordMessage = async (
+  uid: string,
+  cc: string | undefined,
+  fcmToken: string,
+  template: IMessageTemplate,
+  messageData: { [key: string]: string },
+  strategyId: mongoose.Types.ObjectId,
+  strategyName: string
+) => {
   let messageRecord: IMessageRecord | null = null;
   let fcmReceipt = null;
   let messageStatus = 0;
@@ -117,6 +126,7 @@ const sendAndRecordMessage = async (uid: string, fcmToken: string, template: IMe
     // 1. 先创建 MessageRecord 记录,状态为 0 (未发送)
     messageRecord = await MessageRecord.create({
       uid: uid,
+      cc: cc,
       templateId: template._id,
       templateName: template.templateName,
       strategyId: strategyId,
@@ -253,7 +263,7 @@ export async function run(): Promise<void> {
       data1.action = "go/art";
       data1.param = artwork1Id;
 
-      await sendAndRecordMessage(user.uid, fcmToken, messageData.template1, data1, strategy._id, strategy.name);
+      await sendAndRecordMessage(user.uid, user.cc, fcmToken, messageData.template1, data1, strategy._id, strategy.name);
     }
     console.log("第一批消息发送完成。");
 

+ 5 - 1
oms/services/cron-jobs/fcm-notify.ts

@@ -98,6 +98,7 @@ function isTokenInvalidationError(error: any): boolean {
  * 发送即时消息并记录。
  * 此函数将创建数据库记录并立即调用FCM API发送。
  * @param uid 用户ID
+ * @param cc 用户国家代码
  * @param fcmToken 用户的FCM Token
  * @param template 消息模板
  * @param messageData 消息数据
@@ -106,6 +107,7 @@ function isTokenInvalidationError(error: any): boolean {
  */
 const sendImmediateMessageAndRecord = async (
   uid: string,
+  cc: string | undefined,
   fcmToken: string,
   template: IMessageTemplate,
   messageData: { [key: string]: string },
@@ -120,6 +122,7 @@ const sendImmediateMessageAndRecord = async (
   try {
     messageRecord = await MessageRecord.create({
       uid: uid,
+      cc: cc,
       templateId: template._id,
       templateName: template.templateName,
       strategyId: strategyId,
@@ -195,6 +198,7 @@ const createScheduledMessageRecord = async (
   try {
     await MessageRecord.create({
       uid: user.uid,
+      cc: user.cc,
       templateId: template._id,
       templateName: template.templateName,
       strategyId: strategyId,
@@ -291,7 +295,7 @@ export async function run(): Promise<void> {
       data.action = "go/art";
       data.param = artworkId;
 
-      await sendImmediateMessageAndRecord(user.uid, fcmToken, template, data, immediateStrategy._id, immediateStrategy.name);
+      await sendImmediateMessageAndRecord(user.uid, user.cc, fcmToken, template, data, immediateStrategy._id, immediateStrategy.name);
     }
     console.log("即时发送组处理完成。");
 

+ 0 - 15
oms/src/controllers/messageRecordController.ts

@@ -269,21 +269,6 @@ class MessageRecordController {
       return res.status(500).json({ success: false, message: "Server error", error: error.message });
     }
   };
-
-  /**
-   * @route GET /api/message/statistics/avg-delivery-time
-   * @desc Retrieves average message delivery time
-   * @access Private
-   */
-  public getAverageDeliveryTime = async (req: Request, res: Response): Promise<Response> => {
-    try {
-      const stats = await this.messageRecordService.getAverageDeliveryTime();
-      return res.status(200).json({ success: true, data: stats });
-    } catch (error: any) {
-      console.error("Error fetching average delivery time:", error);
-      return res.status(500).json({ success: false, message: "Server error", error: error.message });
-    }
-  };
 }
 
 export default new MessageRecordController();

+ 2 - 0
oms/src/controllers/userController.ts

@@ -267,6 +267,7 @@ class UserController {
       // 3. 先创建 MessageRecord 记录
       const messageRecord = new MessageRecord({
         uid,
+        cc: user.cc,
         title,
         content,
         image,
@@ -382,6 +383,7 @@ class UserController {
         // Create a MessageRecord document before sending.
         const messageRecord = new MessageRecord({
           uid,
+          cc: user.cc,
           title,
           content,
           image,

+ 7 - 0
oms/src/models/messageRecordModel.ts

@@ -16,6 +16,7 @@ export interface IMessageRecord extends Document {
   action?: string;
   param?: string;
   extend?: string;
+  cc?: string; // 新增字段:国家代码
   status: number;
   inforeground?: boolean;
   errno?: string;
@@ -91,6 +92,7 @@ const messageRecordSchema = new Schema<IMessageRecord>(
     // 图片url, 非必须
     image: {
       type: String,
+      index: true,
     },
     // 消息通知的消息是否点击展开查看大图。没有图片的情况下一般就设置成false
     bigger: {
@@ -109,6 +111,11 @@ const messageRecordSchema = new Schema<IMessageRecord>(
     extend: {
       type: String,
     },
+    // 新增字段:国家代码
+    cc: {
+      type: String,
+      index: true,
+    },
     // 0-未发送;1-发送成功;2-已送达;3-已打开;-1-发送失败
     status: {
       type: Number,

+ 0 - 1
oms/src/routes/apiRoutes.ts

@@ -24,7 +24,6 @@ router.get("/message/statistics/by-activity", messageRecordController.getStatist
 router.get("/message/statistics/by-strategy", messageRecordController.getStatisticsByStrategy);
 router.get("/message/statistics/by-template", messageRecordController.getStatisticsByTemplate);
 router.get("/message/statistics/daily-trends", messageRecordController.getDailySentTrends);
-router.get("/message/statistics/avg-delivery-time", messageRecordController.getAverageDeliveryTime);
 
 // 应用认证中间件,保护所有下面的路由
 router.use(authMiddleware);

+ 13 - 3
oms/src/scripts/active-user-daily-notify.ts

@@ -118,13 +118,22 @@ function isTokenInvalidationError(error: any): boolean {
  * 发送并记录FCM消息。
  * 此函数现在将首先创建数据库记录,然后使用该记录的 _id 作为 msgid 进行发送。
  * @param uid 用户ID
+ * @param cc 用户国家代码
  * @param fcmToken 用户的FCM Token
  * @param template 消息模板
  * @param messageData 消息数据
  * @param strategyId 消息策略ID
  * @param strategyName 消息策略名称
  */
-const sendAndRecordMessage = async (uid: string, fcmToken: string, template: IMessageTemplate, messageData: { [key: string]: string }, strategyId: mongoose.Types.ObjectId, strategyName: string) => {
+const sendAndRecordMessage = async (
+  uid: string,
+  cc: string | undefined,
+  fcmToken: string,
+  template: IMessageTemplate,
+  messageData: { [key: string]: string },
+  strategyId: mongoose.Types.ObjectId,
+  strategyName: string
+) => {
   let messageRecord: IMessageRecord | null = null;
   let fcmReceipt = null;
   let messageStatus = 0;
@@ -134,6 +143,7 @@ const sendAndRecordMessage = async (uid: string, fcmToken: string, template: IMe
     // 1. 先创建 MessageRecord 记录,状态为 0 (未发送)
     messageRecord = await MessageRecord.create({
       uid: uid,
+      cc: cc,
       templateId: template._id,
       templateName: template.templateName,
       strategyId: strategyId,
@@ -279,7 +289,7 @@ export async function run(): Promise<void> {
     //   data1.action = "go/art";
     //   data1.param = artwork1Id;
 
-    //   await sendAndRecordMessage(user.uid, fcmToken, messageData.template1, data1, strategy._id, strategy.name);
+    //   await sendAndRecordMessage(user.uid, user.cc, fcmToken, messageData.template1, data1, strategy._id, strategy.name);
     // }
     console.log("第一批消息发送完成。");
 
@@ -299,7 +309,7 @@ export async function run(): Promise<void> {
     //       data2.action = "go/art";
     //       data2.param = artwork2Id;
 
-    //       await sendAndRecordMessage(user.uid, fcmToken, messageData.template2, data2, strategy._id, strategy.name);
+    //       await sendAndRecordMessage(user.uid, user.cc, fcmToken, messageData.template2, data2, strategy._id, strategy.name);
     //     }
     //     console.log("第二批消息发送完成。");
 

+ 55 - 0
oms/src/scripts/backfillCc.ts

@@ -0,0 +1,55 @@
+import mongoose from "mongoose";
+import { MessageRecord } from "../models/messageRecordModel";
+import { User } from "../models/userModel";
+import { connectToDatabase, disconnectFromDatabase } from "../database";
+
+/**
+ * 这是一个用于回填 MessageRecord 表中 cc 字段的脚本。
+ * 它会从 User 表中查找每个 uid 对应的 cc 值,并更新 MessageRecord。
+ */
+const backfillCc = async () => {
+  console.log("[Backfill Script] 开始连接数据库...");
+  await connectToDatabase();
+
+  try {
+    // 仅查询那些缺少 cc 字段的 MessageRecord 文档,以提高效率。
+    // 这也确保了脚本的幂等性,可以安全地多次运行。
+    const recordsToUpdate = MessageRecord.find({ cc: { $exists: false } }).cursor();
+    console.log("[Backfill Script] 找到需要回填的记录。开始处理...");
+
+    let count = 0;
+    // 使用游标(cursor)逐个处理文档,避免一次性加载大量数据到内存中。
+    for await (const record of recordsToUpdate) {
+      count++;
+      console.log(`[Backfill Script] 正在处理第 ${count} 条记录, _id: ${record._id}`);
+
+      // 从用户表中查找对应的 cc 字段,仅投影需要的字段以优化查询性能。
+      const user = await User.findOne({ uid: record.uid }, { cc: 1 }).lean();
+
+      if (user && user.cc) {
+        // 如果找到用户和 cc 字段,则更新 MessageRecord。
+        await MessageRecord.updateOne({ _id: record._id }, { $set: { cc: user.cc } });
+        console.log(`[Backfill Script] 成功为记录 ${record._id} 回填了 cc 字段: ${user.cc}`);
+      } else {
+        // 如果用户或 cc 字段未找到,打印警告信息。
+        console.warn(`[Backfill Script] 未找到用户 ${record.uid} 或其 cc 字段,跳过此记录。`);
+      }
+    }
+
+    console.log(`[Backfill Script] 脚本执行完毕。总共处理了 ${count} 条记录。`);
+  } catch (error) {
+    console.error("[Backfill Script] 脚本执行过程中发生错误:", error);
+  } finally {
+    console.log("[Backfill Script] 断开数据库连接...");
+    await disconnectFromDatabase();
+    process.exit(0);
+  }
+};
+
+// 确保脚本被直接运行时才执行 backfillCc 函数。
+if (require.main === module) {
+  backfillCc().catch((err) => {
+    console.error("脚本启动失败:", err);
+    process.exit(1);
+  });
+}

+ 0 - 44
oms/src/services/messageRecordService.ts

@@ -577,48 +577,4 @@ export class MessageRecordService {
       return [];
     }
   }
-
-  // 消息生命周期分析
-  public async getAverageDeliveryTime() {
-    try {
-      const result = await MessageRecord.aggregate([
-        // 1. 只筛选出已送达的消息(status >= 2)
-        {
-          $match: {
-            status: { $gte: 2 },
-            actualSendAt: { $exists: true, $ne: null },
-            deliveredAt: { $exists: true, $ne: null },
-          },
-        },
-        // 2. 计算每条消息的发送到送达的时间差(毫秒)
-        {
-          $addFields: {
-            time_to_deliver: {
-              $subtract: ["$deliveredAt", "$actualSendAt"],
-            },
-          },
-        },
-        // 3. 计算平均时间
-        {
-          $group: {
-            _id: null,
-            avg_time_to_deliver_ms: { $avg: "$time_to_deliver" },
-          },
-        },
-        // 4. 转换成秒或分钟以方便阅读
-        {
-          $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;
-    }
-  }
 }

+ 0 - 10
omsapp/src/app/pages/message-dashboard.component.ts

@@ -277,16 +277,6 @@ export class MessageDashboardComponent implements OnInit {
             return of([]);
           })
         ),
-      // avgTime: this.http
-      //   .get('/api/message/statistics/avg-delivery-time')
-      //   .pipe(
-      //     map((res: any) => res?.data || null),
-      //     catchError((err) => {
-      //       console.error('Failed to load average delivery time:', err);
-      //       this.message.error('加载平均送达时间失败');
-      //       return of(null);
-      //     })
-      //   ),
     })
       .pipe(
         finalize(() => {

+ 1 - 0
omsapp/src/app/pages/message-record-detail.component.ts

@@ -26,6 +26,7 @@ import { NzModalRef } from 'ng-zorro-antd/modal';
       <nz-descriptions-item nzTitle="用户ID">{{
         record.uid
       }}</nz-descriptions-item>
+      <nz-descriptions-item nzTitle="CC">{{ record.cc }}</nz-descriptions-item>
 
       <!-- 合并活动、策略、模板为一列 -->
       <nz-descriptions-item nzTitle="消息来源">

+ 2 - 0
omsapp/src/app/pages/message-record.component.ts

@@ -195,6 +195,7 @@ import { UserDetailModalComponent } from './user-detail-modal.component';
           <thead>
             <tr>
               <th>用户ID</th>
+              <th>CC</th>
               <th>消息</th>
               <th>来源</th>
               <th>状态</th>
@@ -211,6 +212,7 @@ import { UserDetailModalComponent } from './user-detail-modal.component';
               <td>
                 <a (click)="showUserDetail(record.uid)">{{ record.uid }}</a>
               </td>
+              <td>{{ record.cc }}</td>
               <td class="message-content-cell">
                 <div class="message-title">
                   {{ record.title }}

+ 1 - 0
omsapp/src/app/services/message.service.ts

@@ -181,6 +181,7 @@ export interface MessageActivityData {
 export interface IMessageRecord {
   _id: string;
   uid: string;
+  cc?: string;
   activityId?: string;
   activityName?: string;
   templateId?: string;

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott