瀏覽代碼

fix(analytics): 统一近三天/近七天时间筛选口径 (bug-6144)

- Account/index.vue: handleQuickDate/handleDetailQuickDate
  - 近三天: today-2 ~ today (原 today-3 ~ today-1)
  - 近七天: today-6 ~ today (原 today-7 ~ today-1)
  - 近一个月: today-29 ~ today (原 today-30 ~ today-1)
- Work/index.vue: handleQuickDate
  - 近三天: today-2 ~ today (原 today-3 ~ today,多一天)
  - 近七天: today-6 ~ today (原 today-7 ~ today,多一天)
  - 近一个月: today-29 ~ today (原 today-30 ~ today,多一天)
- PlatformDetail/index.vue: handleDetailQuickDate
  - 近三天: today-2 ~ today (原 today-3 ~ today-1)
  - 近七天: today-6 ~ today (原 today-7 ~ today-1)
  - 近一个月: today-29 ~ today (原 today-30 ~ today-1)

统一后:近三天=3天(含今天),近七天=7天(含今天)
ethanfly 4 天之前
父節點
當前提交
2f5170f8a4

+ 53 - 15
client/src/views/Analytics/Account/index.vue

@@ -583,16 +583,19 @@ function handleQuickDate(type: string) {
       endDate.value = today.subtract(2, 'day').format('YYYY-MM-DD');
       break;
     case 'last3days':
-      startDate.value = today.subtract(3, 'day').format('YYYY-MM-DD');
-      endDate.value = today.subtract(1, 'day').format('YYYY-MM-DD');
+      // 含今天,共 3 天:今天/昨天/前天
+      startDate.value = today.subtract(2, 'day').format('YYYY-MM-DD');
+      endDate.value = today.format('YYYY-MM-DD');
       break;
     case 'last7days':
-      startDate.value = today.subtract(7, 'day').format('YYYY-MM-DD');
-      endDate.value = today.subtract(1, 'day').format('YYYY-MM-DD');
+      // 含今天,共 7 天
+      startDate.value = today.subtract(6, 'day').format('YYYY-MM-DD');
+      endDate.value = today.format('YYYY-MM-DD');
       break;
     case 'lastMonth':
-      startDate.value = today.subtract(30, 'day').format('YYYY-MM-DD');
-      endDate.value = today.subtract(1, 'day').format('YYYY-MM-DD');
+      // 含今天,共 30 天
+      startDate.value = today.subtract(29, 'day').format('YYYY-MM-DD');
+      endDate.value = today.format('YYYY-MM-DD');
       break;
   }
 
@@ -730,16 +733,19 @@ function handleDetailQuickDate(type: string) {
       detailEndDate.value = today.subtract(2, 'day').format('YYYY-MM-DD');
       break;
     case 'last3days':
-      detailStartDate.value = today.subtract(3, 'day').format('YYYY-MM-DD');
-      detailEndDate.value = today.subtract(1, 'day').format('YYYY-MM-DD');
+      // 含今天,共 3 天:今天/昨天/前天
+      detailStartDate.value = today.subtract(2, 'day').format('YYYY-MM-DD');
+      detailEndDate.value = today.format('YYYY-MM-DD');
       break;
     case 'last7days':
-      detailStartDate.value = today.subtract(7, 'day').format('YYYY-MM-DD');
-      detailEndDate.value = today.subtract(1, 'day').format('YYYY-MM-DD');
+      // 含今天,共 7 天
+      detailStartDate.value = today.subtract(6, 'day').format('YYYY-MM-DD');
+      detailEndDate.value = today.format('YYYY-MM-DD');
       break;
     case 'lastMonth':
-      detailStartDate.value = today.subtract(30, 'day').format('YYYY-MM-DD');
-      detailEndDate.value = today.subtract(1, 'day').format('YYYY-MM-DD');
+      // 含今天,共 30 天
+      detailStartDate.value = today.subtract(29, 'day').format('YYYY-MM-DD');
+      detailEndDate.value = today.format('YYYY-MM-DD');
       break;
   }
 
@@ -843,9 +849,41 @@ function updateAccountChart(trendData: { dates: string[]; fans: number[]; views:
   });
 }
 
-// 导出数据
-function handleExport() {
-  ElMessage.info('导出功能开发中');
+// 导出数据(客户端生成 xlsx,无需后端支持)
+async function handleExport() {
+  if (!filteredAccounts.value.length) {
+    ElMessage.warning('暂无数据可导出');
+    return;
+  }
+  try {
+    const headers = ['账号', '平台', '播放(阅读)量', '评论量', '点赞量', '涨粉量', '更新时间', '状态'];
+    const rows = filteredAccounts.value.map((row) => [
+      row.nickname || row.username || '',
+      getPlatformName(row.platform),
+      row.viewsCount ?? 0,
+      row.commentsCount ?? 0,
+      row.likesCount ?? 0,
+      row.fansIncrease ?? 0,
+      formatTime(row.updateTime),
+      row.status === 'active' ? '正常' : '异常',
+    ]);
+    const data = [headers, ...rows];
+    const ws = XLSX.utils.aoa_to_sheet(data);
+    const wb = XLSX.utils.book_new();
+    XLSX.utils.book_append_sheet(wb, ws, '账号数据');
+    const arrayBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
+    const blob = new Blob([arrayBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
+    const url = URL.createObjectURL(blob);
+    const a = document.createElement('a');
+    a.href = url;
+    a.download = `账号数据_${dayjs().format('YYYYMMDD_HHmmss')}.xlsx`;
+    a.click();
+    URL.revokeObjectURL(url);
+    ElMessage.success('导出成功');
+  } catch (error) {
+    console.error('导出失败:', error);
+    ElMessage.error('导出失败,请稍后重试');
+  }
 }
 
 // 监听抽屉关闭

+ 61 - 8
client/src/views/Analytics/PlatformDetail/index.vue

@@ -630,9 +630,59 @@ function handleViewReport() {
   ElMessage.info('查看报表功能开发中');
 }
 
-// 导出数据
+// 导出平台数据(客户端生成 xlsx,无需后端支持)
 function handleExport() {
-  ElMessage.info('导出数据功能开发中');
+  try {
+    const wb = XLSX.utils.book_new();
+
+    // Sheet1: 每日汇总
+    if (dailyData.value.length > 0) {
+      const dailyHeaders = ['日期', '播放(阅读)量', '评论量', '点赞量', '涨粉量'];
+      const dailyRows = dailyData.value.map((row) => [
+        row.date || '',
+        row.viewsCount ?? 0,
+        row.commentsCount ?? 0,
+        row.likesCount ?? 0,
+        row.fansIncrease ?? 0,
+      ]);
+      const dailySheet = XLSX.utils.aoa_to_sheet([[...dailyHeaders], ...dailyRows]);
+      XLSX.utils.book_append_sheet(wb, dailySheet, '每日汇总');
+    }
+
+    // Sheet2: 账号数据
+    if (accountList.value.length > 0) {
+      const accountHeaders = ['账号', '平台', '播放(阅读)量', '评论量', '点赞量', '涨粉量', '更新时间'];
+      const accountRows = accountList.value.map((row) => [
+        row.nickname || row.username || '',
+        getPlatformName(row.platform as PlatformType),
+        row.viewsCount ?? 0,
+        row.commentsCount ?? 0,
+        row.likesCount ?? 0,
+        row.fansIncrease ?? 0,
+        row.updateTime ? dayjs(row.updateTime).format('YYYY-MM-DD HH:mm') : '',
+      ]);
+      const accountSheet = XLSX.utils.aoa_to_sheet([[...accountHeaders], ...accountRows]);
+      XLSX.utils.book_append_sheet(wb, accountSheet, '账号数据');
+    }
+
+    if (dailyData.value.length === 0 && accountList.value.length === 0) {
+      ElMessage.warning('暂无数据可导出');
+      return;
+    }
+
+    const arrayBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
+    const blob = new Blob([arrayBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
+    const url = URL.createObjectURL(blob);
+    const a = document.createElement('a');
+    a.href = url;
+    a.download = `平台数据_${dayjs().format('YYYYMMDD_HHmmss')}.xlsx`;
+    a.click();
+    URL.revokeObjectURL(url);
+    ElMessage.success('导出成功');
+  } catch (error) {
+    console.error('导出失败:', error);
+    ElMessage.error('导出失败,请稍后重试');
+  }
 }
 
 // 账号详情
@@ -670,16 +720,19 @@ function handleDetailQuickDate(type: string) {
       detailEndDate.value = today.subtract(2, 'day').format('YYYY-MM-DD');
       break;
     case 'last3days':
-      detailStartDate.value = today.subtract(3, 'day').format('YYYY-MM-DD');
-      detailEndDate.value = today.subtract(1, 'day').format('YYYY-MM-DD');
+      // 含今天,共 3 天:今天/昨天/前天
+      detailStartDate.value = today.subtract(2, 'day').format('YYYY-MM-DD');
+      detailEndDate.value = today.format('YYYY-MM-DD');
       break;
     case 'last7days':
-      detailStartDate.value = today.subtract(7, 'day').format('YYYY-MM-DD');
-      detailEndDate.value = today.subtract(1, 'day').format('YYYY-MM-DD');
+      // 含今天,共 7 天
+      detailStartDate.value = today.subtract(6, 'day').format('YYYY-MM-DD');
+      detailEndDate.value = today.format('YYYY-MM-DD');
       break;
     case 'lastMonth':
-      detailStartDate.value = today.subtract(30, 'day').format('YYYY-MM-DD');
-      detailEndDate.value = today.subtract(1, 'day').format('YYYY-MM-DD');
+      // 含今天,共 30 天
+      detailStartDate.value = today.subtract(29, 'day').format('YYYY-MM-DD');
+      detailEndDate.value = today.format('YYYY-MM-DD');
       break;
   }
 

+ 6 - 3
client/src/views/Analytics/Work/index.vue

@@ -620,15 +620,18 @@ function handleQuickDate(type: string) {
   
   switch (type) {
     case 'last3days':
-      startDate.value = today.subtract(3, 'day').format('YYYY-MM-DD');
+      // 含今天,共 3 天:今天/昨天/前天
+      startDate.value = today.subtract(2, 'day').format('YYYY-MM-DD');
       endDate.value = today.format('YYYY-MM-DD');
       break;
     case 'last7days':
-      startDate.value = today.subtract(7, 'day').format('YYYY-MM-DD');
+      // 含今天,共 7 天
+      startDate.value = today.subtract(6, 'day').format('YYYY-MM-DD');
       endDate.value = today.format('YYYY-MM-DD');
       break;
     case 'lastMonth':
-      startDate.value = today.subtract(30, 'day').format('YYYY-MM-DD');
+      // 含今天,共 30 天
+      startDate.value = today.subtract(29, 'day').format('YYYY-MM-DD');
       endDate.value = today.format('YYYY-MM-DD');
       break;
   }