浏览代码

增加展示人数,点击人数, 实际点击率统计

guoziyun 9 月之前
父节点
当前提交
9935bc8879

文件差异内容过多而无法显示
+ 94 - 956
oms/dist/src/services/messageRecordService.js


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

文件差异内容过多而无法显示
+ 0 - 0
oms/public/app/main-FKSCPF2E.js


文件差异内容过多而无法显示
+ 81 - 945
oms/src/services/messageRecordService.ts


+ 258 - 1
omsapp/src/app/pages/message-dashboard.component.html

@@ -75,9 +75,25 @@
             nzTitle="点击率"
             [nzValue]="formatPercentage(overallStats.clickThroughRate || 0)"
           ></nz-statistic>
+          <div class="statistic-subtext">
+            点击数: {{ overallStats.opened || 0 }}
+          </div>
         </div>
 
         <div nz-col [nzSpan]="4">
+          <nz-statistic
+            nzTitle="实际点击率"
+            [nzValue]="
+              formatPercentage(overallStats.actualClickThroughRate || 0)
+            "
+          ></nz-statistic>
+          <div class="statistic-subtext">
+            点击人数: {{ overallStats.openedUsers || 0 }} / 展示人数:
+            {{ overallStats.displayedUsers || 0 }}
+          </div>
+        </div>
+
+        <!-- <div nz-col [nzSpan]="4">
           <nz-statistic
             nzTitle="失败率"
             [nzValue]="
@@ -87,7 +103,7 @@
           <div class="statistic-subtext">
             失败数: {{ overallStats.failed || 0 }}
           </div>
-        </div>
+        </div> -->
       </div>
     </nz-card>
 
@@ -146,6 +162,20 @@
               ></span>
               失败数
             </div>
+            <div>
+              <span
+                class="legend-color"
+                style="background-color: #482880"
+              ></span>
+              展示用户
+            </div>
+            <div>
+              <span
+                class="legend-color"
+                style="background-color: #0066cc"
+              ></span>
+              打开用户
+            </div>
             <div>
               <span class="legend-line" style="border-color: #13c2c2"></span>
               送达率
@@ -158,6 +188,10 @@
               <span class="legend-line" style="border-color: #722ed1"></span>
               点击率
             </div>
+            <div>
+              <span class="legend-line" style="border-color: #fb56fb"></span>
+              实际点击率
+            </div>
           </div>
         </nz-card>
       </div>
@@ -257,6 +291,32 @@
                   ></i>
                 </span>
               </th>
+              <th (click)="sortStrategyTable('displayedUsers')">
+                展示用户
+                <span *ngIf="strategySortField === 'displayedUsers'">
+                  <i
+                    nz-icon
+                    [nzType]="
+                      strategySortDirection === 'ascend'
+                        ? 'caret-up'
+                        : 'caret-down'
+                    "
+                  ></i>
+                </span>
+              </th>
+              <th (click)="sortStrategyTable('openedUsers')">
+                打开用户
+                <span *ngIf="strategySortField === 'openedUsers'">
+                  <i
+                    nz-icon
+                    [nzType]="
+                      strategySortDirection === 'ascend'
+                        ? 'caret-up'
+                        : 'caret-down'
+                    "
+                  ></i>
+                </span>
+              </th>
               <th (click)="sortStrategyTable('failed')">
                 失败数
                 <span *ngIf="strategySortField === 'failed'">
@@ -270,6 +330,7 @@
                   ></i>
                 </span>
               </th>
+
               <th (click)="sortStrategyTable('deliveredRate')">
                 送达率
                 <span *ngIf="strategySortField === 'deliveredRate'">
@@ -309,6 +370,19 @@
                   ></i>
                 </span>
               </th>
+              <th (click)="sortStrategyTable('actualClickThroughRate')">
+                实际点击率
+                <span *ngIf="strategySortField === 'actualClickThroughRate'">
+                  <i
+                    nz-icon
+                    [nzType]="
+                      strategySortDirection === 'ascend'
+                        ? 'caret-up'
+                        : 'caret-down'
+                    "
+                  ></i>
+                </span>
+              </th>
               <th (click)="sortStrategyTable('tokenInvalidationRate')">
                 失败率
                 <span *ngIf="strategySortField === 'tokenInvalidationRate'">
@@ -351,10 +425,15 @@
                 <td>{{ item.delivered || 0 }}</td>
                 <td>{{ item.displayCount || 0 }}</td>
                 <td>{{ item.opened || 0 }}</td>
+                <td>{{ item.displayedUsers || 0 }}</td>
+                <td>{{ item.openedUsers || 0 }}</td>
                 <td>{{ item.failed || 0 }}</td>
                 <td>{{ formatPercentage(item.deliveredRate || 0) }}</td>
                 <td>{{ formatPercentage(item.displayRate || 0) }}</td>
                 <td>{{ formatPercentage(item.clickThroughRate || 0) }}</td>
+                <td>
+                  {{ formatPercentage(item.actualClickThroughRate || 0) }}
+                </td>
                 <td>{{ formatPercentage(item.tokenInvalidationRate || 0) }}</td>
               </tr>
               <tr [nzExpand]="item.expanded">
@@ -381,10 +460,13 @@
                           <th>送达数</th>
                           <th>展示数</th>
                           <th>打开数</th>
+                          <th>展示人数</th>
+                          <th>打开人数</th>
                           <th>失败数</th>
                           <th>送达率</th>
                           <th>展示率</th>
                           <th>点击率</th>
+                          <th>实际点击率</th>
                           <th>失败率</th>
                         </tr>
                       </thead>
@@ -395,7 +477,10 @@
                           <td>{{ daily.sent || 0 }}</td>
                           <td>{{ daily.delivered || 0 }}</td>
                           <td>{{ daily.displayCount || 0 }}</td>
+
                           <td>{{ daily.opened || 0 }}</td>
+                          <td>{{ daily.displayedUsers || 0 }}</td>
+                          <td>{{ daily.openedUsers || 0 }}</td>
                           <td>{{ daily.failed || 0 }}</td>
                           <td>
                             {{ formatPercentage(daily.deliveredRate || 0) }}
@@ -406,6 +491,13 @@
                           <td>
                             {{ formatPercentage(daily.clickThroughRate || 0) }}
                           </td>
+                          <td>
+                            {{
+                              formatPercentage(
+                                daily.actualClickThroughRate || 0
+                              )
+                            }}
+                          </td>
                           <td>
                             {{
                               formatPercentage(daily.tokenInvalidationRate || 0)
@@ -515,6 +607,32 @@
                   ></i>
                 </span>
               </th>
+              <th (click)="sortTemplateTable('displayedUsers')">
+                展示用户
+                <span *ngIf="templateSortField === 'displayedUsers'">
+                  <i
+                    nz-icon
+                    [nzType]="
+                      templateSortDirection === 'ascend'
+                        ? 'caret-up'
+                        : 'caret-down'
+                    "
+                  ></i>
+                </span>
+              </th>
+              <th (click)="sortTemplateTable('openedUsers')">
+                打开用户
+                <span *ngIf="templateSortField === 'openedUsers'">
+                  <i
+                    nz-icon
+                    [nzType]="
+                      templateSortDirection === 'ascend'
+                        ? 'caret-up'
+                        : 'caret-down'
+                    "
+                  ></i>
+                </span>
+              </th>
               <th (click)="sortTemplateTable('failed')">
                 失败数
                 <span *ngIf="templateSortField === 'failed'">
@@ -528,6 +646,7 @@
                   ></i>
                 </span>
               </th>
+
               <th (click)="sortTemplateTable('deliveredRate')">
                 送达率
                 <span *ngIf="templateSortField === 'deliveredRate'">
@@ -567,6 +686,19 @@
                   ></i>
                 </span>
               </th>
+              <th (click)="sortTemplateTable('actualClickThroughRate')">
+                实际点击率
+                <span *ngIf="templateSortField === 'actualClickThroughRate'">
+                  <i
+                    nz-icon
+                    [nzType]="
+                      templateSortDirection === 'ascend'
+                        ? 'caret-up'
+                        : 'caret-down'
+                    "
+                  ></i>
+                </span>
+              </th>
               <th (click)="sortTemplateTable('tokenInvalidationRate')">
                 失败率
                 <span *ngIf="templateSortField === 'tokenInvalidationRate'">
@@ -609,10 +741,15 @@
                 <td>{{ item.delivered || 0 }}</td>
                 <td>{{ item.displayCount || 0 }}</td>
                 <td>{{ item.opened || 0 }}</td>
+                <td>{{ item.displayedUsers || 0 }}</td>
+                <td>{{ item.openedUsers || 0 }}</td>
                 <td>{{ item.failed || 0 }}</td>
                 <td>{{ formatPercentage(item.deliveredRate || 0) }}</td>
                 <td>{{ formatPercentage(item.displayRate || 0) }}</td>
                 <td>{{ formatPercentage(item.clickThroughRate || 0) }}</td>
+                <td>
+                  {{ formatPercentage(item.actualClickThroughRate || 0) }}
+                </td>
                 <td>{{ formatPercentage(item.tokenInvalidationRate || 0) }}</td>
               </tr>
               <tr [nzExpand]="item.expanded">
@@ -639,10 +776,13 @@
                           <th>送达数</th>
                           <th>展示数</th>
                           <th>打开数</th>
+                          <th>展示人数</th>
+                          <th>打开人数</th>
                           <th>失败数</th>
                           <th>送达率</th>
                           <th>展示率</th>
                           <th>点击率</th>
+                          <th>实际点击率</th>
                           <th>失败率</th>
                         </tr>
                       </thead>
@@ -654,6 +794,8 @@
                           <td>{{ daily.delivered || 0 }}</td>
                           <td>{{ daily.displayCount || 0 }}</td>
                           <td>{{ daily.opened || 0 }}</td>
+                          <td>{{ daily.displayedUsers || 0 }}</td>
+                          <td>{{ daily.openedUsers || 0 }}</td>
                           <td>{{ daily.failed || 0 }}</td>
                           <td>
                             {{ formatPercentage(daily.deliveredRate || 0) }}
@@ -664,6 +806,13 @@
                           <td>
                             {{ formatPercentage(daily.clickThroughRate || 0) }}
                           </td>
+                          <td>
+                            {{
+                              formatPercentage(
+                                daily.actualClickThroughRate || 0
+                              )
+                            }}
+                          </td>
                           <td>
                             {{
                               formatPercentage(daily.tokenInvalidationRate || 0)
@@ -761,6 +910,28 @@
                   ></i>
                 </span>
               </th>
+              <th (click)="sortCcTable('displayedUsers')">
+                展示用户
+                <span *ngIf="ccSortField === 'displayedUsers'">
+                  <i
+                    nz-icon
+                    [nzType]="
+                      ccSortDirection === 'ascend' ? 'caret-up' : 'caret-down'
+                    "
+                  ></i>
+                </span>
+              </th>
+              <th (click)="sortCcTable('openedUsers')">
+                打开用户
+                <span *ngIf="ccSortField === 'openedUsers'">
+                  <i
+                    nz-icon
+                    [nzType]="
+                      ccSortDirection === 'ascend' ? 'caret-up' : 'caret-down'
+                    "
+                  ></i>
+                </span>
+              </th>
               <th (click)="sortCcTable('failed')">
                 失败数
                 <span *ngIf="ccSortField === 'failed'">
@@ -805,6 +976,17 @@
                   ></i>
                 </span>
               </th>
+              <th (click)="sortCcTable('actualClickThroughRate')">
+                实际点击率
+                <span *ngIf="ccSortField === 'actualClickThroughRate'">
+                  <i
+                    nz-icon
+                    [nzType]="
+                      ccSortDirection === 'ascend' ? 'caret-up' : 'caret-down'
+                    "
+                  ></i>
+                </span>
+              </th>
               <th (click)="sortCcTable('tokenInvalidationRate')">
                 失败率
                 <span *ngIf="ccSortField === 'tokenInvalidationRate'">
@@ -836,10 +1018,15 @@
                 <td>{{ item.delivered || 0 }}</td>
                 <td>{{ item.displayCount || 0 }}</td>
                 <td>{{ item.opened || 0 }}</td>
+                <td>{{ item.displayedUsers || 0 }}</td>
+                <td>{{ item.openedUsers || 0 }}</td>
                 <td>{{ item.failed || 0 }}</td>
                 <td>{{ formatPercentage(item.deliveredRate || 0) }}</td>
                 <td>{{ formatPercentage(item.displayRate || 0) }}</td>
                 <td>{{ formatPercentage(item.clickThroughRate || 0) }}</td>
+                <td>
+                  {{ formatPercentage(item.actualClickThroughRate || 0) }}
+                </td>
                 <td>{{ formatPercentage(item.tokenInvalidationRate || 0) }}</td>
               </tr>
               <tr [nzExpand]="item.expanded">
@@ -866,10 +1053,13 @@
                           <th>送达数</th>
                           <th>展示数</th>
                           <th>打开数</th>
+                          <th>展示人数</th>
+                          <th>打开人数</th>
                           <th>失败数</th>
                           <th>送达率</th>
                           <th>展示率</th>
                           <th>点击率</th>
+                          <th>实际点击率</th>
                           <th>失败率</th>
                         </tr>
                       </thead>
@@ -881,6 +1071,8 @@
                           <td>{{ daily.delivered || 0 }}</td>
                           <td>{{ daily.displayCount || 0 }}</td>
                           <td>{{ daily.opened || 0 }}</td>
+                          <td>{{ daily.displayedUsers || 0 }}</td>
+                          <td>{{ daily.openedUsers || 0 }}</td>
                           <td>{{ daily.failed || 0 }}</td>
                           <td>
                             {{ formatPercentage(daily.deliveredRate || 0) }}
@@ -891,6 +1083,13 @@
                           <td>
                             {{ formatPercentage(daily.clickThroughRate || 0) }}
                           </td>
+                          <td>
+                            {{
+                              formatPercentage(
+                                daily.actualClickThroughRate || 0
+                              )
+                            }}
+                          </td>
                           <td>
                             {{
                               formatPercentage(daily.tokenInvalidationRate || 0)
@@ -988,6 +1187,32 @@
                   ></i>
                 </span>
               </th>
+              <th (click)="sortImageTable('displayedUsers')">
+                展示用户
+                <span *ngIf="imageSortField === 'displayedUsers'">
+                  <i
+                    nz-icon
+                    [nzType]="
+                      imageSortDirection === 'ascend'
+                        ? 'caret-up'
+                        : 'caret-down'
+                    "
+                  ></i>
+                </span>
+              </th>
+              <th (click)="sortImageTable('openedUsers')">
+                打开用户
+                <span *ngIf="imageSortField === 'openedUsers'">
+                  <i
+                    nz-icon
+                    [nzType]="
+                      imageSortDirection === 'ascend'
+                        ? 'caret-up'
+                        : 'caret-down'
+                    "
+                  ></i>
+                </span>
+              </th>
               <th (click)="sortImageTable('failed')">
                 失败数
                 <span *ngIf="imageSortField === 'failed'">
@@ -1040,6 +1265,19 @@
                   ></i>
                 </span>
               </th>
+              <th (click)="sortImageTable('actualClickThroughRate')">
+                实际点击率
+                <span *ngIf="imageSortField === 'actualClickThroughRate'">
+                  <i
+                    nz-icon
+                    [nzType]="
+                      imageSortDirection === 'ascend'
+                        ? 'caret-up'
+                        : 'caret-down'
+                    "
+                  ></i>
+                </span>
+              </th>
               <th (click)="sortImageTable('tokenInvalidationRate')">
                 失败率
                 <span *ngIf="imageSortField === 'tokenInvalidationRate'">
@@ -1084,10 +1322,15 @@
                 <td>{{ item.delivered || 0 }}</td>
                 <td>{{ item.displayCount || 0 }}</td>
                 <td>{{ item.opened || 0 }}</td>
+                <td>{{ item.displayedUsers || 0 }}</td>
+                <td>{{ item.openedUsers || 0 }}</td>
                 <td>{{ item.failed || 0 }}</td>
                 <td>{{ formatPercentage(item.deliveredRate || 0) }}</td>
                 <td>{{ formatPercentage(item.displayRate || 0) }}</td>
                 <td>{{ formatPercentage(item.clickThroughRate || 0) }}</td>
+                <td>
+                  {{ formatPercentage(item.actualClickThroughRate || 0) }}
+                </td>
                 <td>{{ formatPercentage(item.tokenInvalidationRate || 0) }}</td>
               </tr>
               <tr [nzExpand]="item.expanded">
@@ -1114,10 +1357,14 @@
                           <th>送达数</th>
                           <th>展示数</th>
                           <th>打开数</th>
+                          <th>展示人数</th>
+                          <th>打开人数</th>
                           <th>失败数</th>
                           <th>送达率</th>
                           <th>展示率</th>
                           <th>点击率</th>
+
+                          <th>实际点击率</th>
                           <th>失败率</th>
                         </tr>
                       </thead>
@@ -1129,6 +1376,8 @@
                           <td>{{ daily.delivered || 0 }}</td>
                           <td>{{ daily.displayCount || 0 }}</td>
                           <td>{{ daily.opened || 0 }}</td>
+                          <td>{{ daily.displayedUsers || 0 }}</td>
+                          <td>{{ daily.openedUsers || 0 }}</td>
                           <td>{{ daily.failed || 0 }}</td>
                           <td>
                             {{ formatPercentage(daily.deliveredRate || 0) }}
@@ -1139,6 +1388,14 @@
                           <td>
                             {{ formatPercentage(daily.clickThroughRate || 0) }}
                           </td>
+
+                          <td>
+                            {{
+                              formatPercentage(
+                                daily.actualClickThroughRate || 0
+                              )
+                            }}
+                          </td>
                           <td>
                             {{
                               formatPercentage(daily.tokenInvalidationRate || 0)

+ 43 - 4
omsapp/src/app/pages/message-dashboard.component.ts

@@ -146,6 +146,18 @@ export class MessageDashboardComponent implements OnInit {
         backgroundColor: '#f5222d',
         yAxisID: 'y',
       },
+      {
+        label: '展示用户',
+        data: [],
+        backgroundColor: '#482880',
+        yAxisID: 'y',
+      },
+      {
+        label: '打开用户',
+        data: [],
+        backgroundColor: '#0066CC',
+        yAxisID: 'y',
+      },
       // 折线图数据集
       {
         label: '送达率',
@@ -183,6 +195,18 @@ export class MessageDashboardComponent implements OnInit {
         pointRadius: 4,
         pointHoverRadius: 6,
       },
+      {
+        label: '实际点击率',
+        data: [],
+        borderColor: '#fb56fb',
+        backgroundColor: 'transparent',
+        yAxisID: 'y1',
+        type: 'line',
+        tension: 0.3,
+        borderWidth: 2,
+        pointRadius: 4,
+        pointHoverRadius: 6,
+      },
     ],
   };
 
@@ -200,7 +224,7 @@ export class MessageDashboardComponent implements OnInit {
               label += ': ';
             }
             // 如果是折线图(转化率),格式化显示两位小数并添加百分号
-            if (context.datasetIndex >= 6) {
+            if (context.datasetIndex >= 8) {
               // 假设6-8是折线图数据集
               const value = typeof context.raw === 'number' ? context.raw : 0;
               label += value.toFixed(2) + '%';
@@ -580,25 +604,40 @@ export class MessageDashboardComponent implements OnInit {
           ...this.combinedChartData.datasets[5],
           data: this.dailyTrends.map((t) => t.failed || 0),
         },
-        // 折线图数据
         {
           ...this.combinedChartData.datasets[6],
+          data: this.dailyTrends.map((t) => t.displayedUsers || 0),
+        },
+        {
+          ...this.combinedChartData.datasets[7],
+          data: this.dailyTrends.map((t) => t.openedUsers || 0),
+        },
+
+        // 折线图数据
+        {
+          ...this.combinedChartData.datasets[8],
           data: this.dailyTrends.map((t) =>
             this.preciseRound((t.deliveredRate || 0) * 100, 2)
           ),
         },
         {
-          ...this.combinedChartData.datasets[7],
+          ...this.combinedChartData.datasets[9],
           data: this.dailyTrends.map((t) =>
             this.preciseRound((t.displayRate || 0) * 100, 2)
           ),
         },
         {
-          ...this.combinedChartData.datasets[8],
+          ...this.combinedChartData.datasets[10],
           data: this.dailyTrends.map((t) =>
             this.preciseRound((t.clickThroughRate || 0) * 100, 2)
           ),
         },
+        {
+          ...this.combinedChartData.datasets[11],
+          data: this.dailyTrends.map((t) =>
+            this.preciseRound((t.actualClickThroughRate || 0) * 100, 2)
+          ),
+        },
       ],
     };
   }

部分文件因为文件数量过多而无法显示