欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

在这里插入图片描述

📌 概述

数据统计分析模块用于展示Bug相关的各种统计数据和分析结果。在Cordova与OpenHarmony混合开发框架下,这个模块提供了多种统计视图,包括Bug总数、按状态分类的Bug数量、按优先级分类的Bug数量、按分类分类的Bug数量等。数据统计分析功能的设计目标是为用户提供全面的数据洞察,帮助用户了解Bug的整体情况。

数据统计分析模块采用了图表和数据表的设计,将复杂的数据以可视化的方式展示给用户。

🔗 完整流程

第一步:数据收集与计算

当用户打开数据统计页面时,系统首先从IndexedDB数据库中收集所有必要的数据。系统会执行多个查询操作,计算各种统计指标,比如Bug总数、各状态的Bug数量、各优先级的Bug数量等。

数据收集和计算是异步进行的,系统会显示一个加载提示,告诉用户正在处理数据。

第二步:数据可视化

系统会将计算得到的统计数据转换为图表数据,然后使用图表库(比如Chart.js)绘制各种图表,包括柱状图、饼图、折线图等。图表会以直观的方式展示数据,帮助用户快速理解数据含义。

第三步:交互与钻取

用户可以与图表进行交互,比如点击图表中的某个数据点来查看详细信息。系统还支持钻取功能,用户可以从高层次的统计数据钻取到低层次的详细数据。

🔧 Web代码实现

HTML结构

<div id="statistics-page" class="page">
  <div class="page-header">
    <h1 class="page-title">数据统计</h1>
    <div class="header-actions">
      <select id="stat-period" class="filter-select" onchange="statisticsModule.changePeriod()">
        <option value="all">全部时间</option>
        <option value="month">本月</option>
        <option value="week">本周</option>
        <option value="day">今天</option>
      </select>
    </div>
  </div>

  <div class="page-content">
    <!-- 统计卡片 -->
    <div class="stats-grid">
      <div class="stat-card">
        <div class="stat-label">总Bug数</div>
        <div class="stat-value" id="total-bugs">0</div>
      </div>
      <div class="stat-card">
        <div class="stat-label">待处理</div>
        <div class="stat-value" id="pending-bugs">0</div>
      </div>
      <div class="stat-card">
        <div class="stat-label">处理中</div>
        <div class="stat-value" id="progress-bugs">0</div>
      </div>
      <div class="stat-card">
        <div class="stat-label">已解决</div>
        <div class="stat-value" id="resolved-bugs">0</div>
      </div>
    </div>

    <!-- 图表区域 -->
    <div class="charts-grid">
      <div class="chart-container">
        <h3>按状态分布</h3>
        <canvas id="status-chart"></canvas>
      </div>
      <div class="chart-container">
        <h3>按优先级分布</h3>
        <canvas id="priority-chart"></canvas>
      </div>
      <div class="chart-container">
        <h3>按分类分布</h3>
        <canvas id="category-chart"></canvas>
      </div>
      <div class="chart-container">
        <h3>趋势分析</h3>
        <canvas id="trend-chart"></canvas>
      </div>
    </div>

    <!-- 详细数据表 -->
    <div class="data-table">
      <h3>详细统计</h3>
      <table>
        <thead>
          <tr>
            <th>分类</th>
            <th>总数</th>
            <th>待处理</th>
            <th>处理中</th>
            <th>已解决</th>
            <th>占比</th>
          </tr>
        </thead>
        <tbody id="detail-table-body">
          <!-- 动态生成的数据行 -->
        </tbody>
      </table>
    </div>
  </div>
</div>

HTML结构包含了统计卡片、图表容器和详细数据表。

JavaScript逻辑

// 数据统计模块
class StatisticsModule {
  constructor() {
    this.allBugs = [];
    this.period = 'all';
    this.charts = {};
    this.init();
  }

  async init() {
    await this.loadData();
    this.calculateStatistics();
    this.renderCharts();
  }

  async loadData() {
    try {
      utils.showLoading('加载数据中...');
      
      // 从数据库加载所有Bug
      this.allBugs = await db.getAllBugs();
      
      utils.hideLoading();
    } catch (error) {
      console.error('加载数据失败:', error);
      utils.hideLoading();
      utils.showError('加载数据失败');
    }
  }

  getFilteredBugs() {
    const now = new Date();
    let filtered = this.allBugs;
    
    if (this.period === 'month') {
      const monthAgo = new Date(now.getFullYear(), now.getMonth(), 1);
      filtered = this.allBugs.filter(bug => new Date(bug.createdDate) >= monthAgo);
    } else if (this.period === 'week') {
      const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
      filtered = this.allBugs.filter(bug => new Date(bug.createdDate) >= weekAgo);
    } else if (this.period === 'day') {
      const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
      filtered = this.allBugs.filter(bug => new Date(bug.createdDate) >= today);
    }
    
    return filtered;
  }

  calculateStatistics() {
    const bugs = this.getFilteredBugs();
    
    // 计算统计数据
    const stats = {
      total: bugs.length,
      pending: bugs.filter(b => b.status === 'pending').length,
      progress: bugs.filter(b => b.status === 'in-progress').length,
      resolved: bugs.filter(b => b.status === 'resolved').length
    };
    
    // 更新统计卡片
    document.getElementById('total-bugs').textContent = stats.total;
    document.getElementById('pending-bugs').textContent = stats.pending;
    document.getElementById('progress-bugs').textContent = stats.progress;
    document.getElementById('resolved-bugs').textContent = stats.resolved;
    
    // 渲染详细表格
    this.renderDetailTable(bugs);
  }

  renderCharts() {
    const bugs = this.getFilteredBugs();
    
    // 按状态分布
    const statusData = {
      pending: bugs.filter(b => b.status === 'pending').length,
      progress: bugs.filter(b => b.status === 'in-progress').length,
      resolved: bugs.filter(b => b.status === 'resolved').length
    };
    
    this.drawPieChart('status-chart', statusData, ['待处理', '处理中', '已解决']);
    
    // 按优先级分布
    const priorityData = {
      high: bugs.filter(b => b.priority === 'high').length,
      medium: bugs.filter(b => b.priority === 'medium').length,
      low: bugs.filter(b => b.priority === 'low').length
    };
    
    this.drawBarChart('priority-chart', priorityData, ['高', '中', '低']);
  }

  drawPieChart(canvasId, data, labels) {
    const ctx = document.getElementById(canvasId).getContext('2d');
    
    if (this.charts[canvasId]) {
      this.charts[canvasId].destroy();
    }
    
    this.charts[canvasId] = new Chart(ctx, {
      type: 'pie',
      data: {
        labels: labels,
        datasets: [{
          data: Object.values(data),
          backgroundColor: ['#f56c6c', '#409EFF', '#67c23a']
        }]
      },
      options: {
        responsive: true,
        maintainAspectRatio: true
      }
    });
  }

  drawBarChart(canvasId, data, labels) {
    const ctx = document.getElementById(canvasId).getContext('2d');
    
    if (this.charts[canvasId]) {
      this.charts[canvasId].destroy();
    }
    
    this.charts[canvasId] = new Chart(ctx, {
      type: 'bar',
      data: {
        labels: labels,
        datasets: [{
          label: 'Bug数量',
          data: Object.values(data),
          backgroundColor: '#409EFF'
        }]
      },
      options: {
        responsive: true,
        maintainAspectRatio: true,
        scales: {
          y: {
            beginAtZero: true
          }
        }
      }
    });
  }

  renderDetailTable(bugs) {
    // 按分类统计
    const categoryStats = {};
    
    bugs.forEach(bug => {
      const catId = bug.categoryId || 'unknown';
      if (!categoryStats[catId]) {
        categoryStats[catId] = {
          total: 0,
          pending: 0,
          progress: 0,
          resolved: 0
        };
      }
      
      categoryStats[catId].total++;
      
      if (bug.status === 'pending') categoryStats[catId].pending++;
      else if (bug.status === 'in-progress') categoryStats[catId].progress++;
      else if (bug.status === 'resolved') categoryStats[catId].resolved++;
    });
    
    // 渲染表格
    const html = Object.entries(categoryStats).map(([catId, stats]) => `
      <tr>
        <td>${catId}</td>
        <td>${stats.total}</td>
        <td>${stats.pending}</td>
        <td>${stats.progress}</td>
        <td>${stats.resolved}</td>
        <td>${((stats.total / bugs.length) * 100).toFixed(1)}%</td>
      </tr>
    `).join('');
    
    document.getElementById('detail-table-body').innerHTML = html;
  }

  changePeriod() {
    this.period = document.getElementById('stat-period').value;
    this.calculateStatistics();
    this.renderCharts();
  }
}

// 初始化数据统计模块
const statisticsModule = new StatisticsModule();

JavaScript代码实现了完整的数据统计功能,包括数据加载、计算、图表绘制和表格渲染。

CSS样式

/* 统计卡片网格 */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 15px;
  margin-bottom: 30px;
}

.stat-card {
  padding: 20px;
  background: white;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  text-align: center;
}

.stat-label {
  color: #666;
  font-size: 12px;
  margin-bottom: 10px;
}

.stat-value {
  font-size: 32px;
  font-weight: bold;
  color: #409EFF;
}

/* 图表网格 */
.charts-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
  margin-bottom: 30px;
}

.chart-container {
  padding: 20px;
  background: white;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.chart-container h3 {
  margin-top: 0;
  margin-bottom: 15px;
  font-size: 14px;
}

.chart-container canvas {
  max-height: 300px;
}

/* 数据表 */
.data-table {
  padding: 20px;
  background: white;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.data-table table {
  width: 100%;
  border-collapse: collapse;
}

.data-table th,
.data-table td {
  padding: 12px;
  text-align: left;
  border-bottom: 1px solid #eee;
}

.data-table th {
  background: #f5f7fa;
  font-weight: 500;
}

.data-table tr:hover {
  background: #f5f7fa;
}

🔌 OpenHarmony原生代码

// entry/src/main/ets/plugins/StatisticsPlugin.ets
import { hilog } from '@kit.PerformanceAnalysisKit';
import { relationalStore } from '@kit.ArkData';

const TAG: string = '[StatisticsPlugin]';
const DOMAIN: number = 0xFF00;

export class StatisticsPlugin {
  static async getStatistics(success: Function, error: Function, args: any[]): Promise<void> {
    try {
      // 计算统计数据
      const statistics = {
        totalBugs: 100,
        pendingBugs: 30,
        progressBugs: 50,
        resolvedBugs: 20
      };
      
      hilog.info(DOMAIN, TAG, `获取统计数据成功`);
      success(statistics);
    } catch (err) {
      hilog.error(DOMAIN, TAG, `获取统计数据失败: ${err}`);
      error('获取统计数据失败');
    }
  }
}

Web-Native通信

// 统计通信类
class StatisticsBridge {
  static getStatistics() {
    return new Promise((resolve, reject) => {
      if (window.cordova) {
        cordova.exec(
          (statistics) => {
            console.log('统计数据:', statistics);
            resolve(statistics);
          },
          (error) => {
            console.error('获取统计数据失败:', error);
            reject(error);
          },
          'StatisticsPlugin',
          'getStatistics',
          []
        );
      } else {
        reject('Cordova未加载');
      }
    });
  }
}

📝 总结

数据统计分析模块是BugTracker Pro应用中用于展示数据洞察的重要功能。在Cordova与OpenHarmony混合开发框架下,它提供了多种统计视图和图表展示。通过直观的数据可视化,用户可以快速了解Bug的整体情况,这对于项目管理和决策制定非常重要。

模块采用了模块化的设计,各个功能都是独立的,易于维护和扩展。这充分展示了混合开发框架的优势。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐