鸿蒙交易记录可视化(分类统计/账单导出)

举报
鱼弦 发表于 2025/10/20 09:10:57 2025/10/20
【摘要】 一、引言在移动支付与个人财务管理日益普及的今天,用户对交易记录的 ​​可视化分析​​ 和 ​​灵活导出​​ 需求愈发强烈。传统的交易记录仅以列表形式展示,缺乏直观的分类统计(如餐饮、交通、购物等消费占比)和便捷的账单导出功能(如导出为Excel/CSV供记账软件使用),导致用户难以快速掌握消费规律或进行财务对账。鸿蒙操作系统(HarmonyOS)凭借其 ​​分布式数据管理​​ 和 ​​UI组...


一、引言

在移动支付与个人财务管理日益普及的今天,用户对交易记录的 ​​可视化分析​​ 和 ​​灵活导出​​ 需求愈发强烈。传统的交易记录仅以列表形式展示,缺乏直观的分类统计(如餐饮、交通、购物等消费占比)和便捷的账单导出功能(如导出为Excel/CSV供记账软件使用),导致用户难以快速掌握消费规律或进行财务对账。
鸿蒙操作系统(HarmonyOS)凭借其 ​​分布式数据管理​​ 和 ​​UI组件灵活性​​,为开发者提供了构建交易记录可视化应用的理想平台。通过结合 ​​分类统计图表(如饼图/柱状图)​​ 和 ​​账单导出功能(文件生成与分享)​​,用户可以清晰查看消费分布、快速定位大额支出,并将账单数据导出至其他应用(如Excel、微信)进行进一步处理。
本文将围绕鸿蒙交易记录可视化的核心技术(分类统计、账单导出),结合实际代码示例与原理解析,详细介绍如何构建一个功能完善、体验流畅的财务可视化应用。

二、技术背景

1. 交易记录可视化的核心需求

用户对交易记录管理的需求已从“单纯存储”升级为“智能分析+灵活导出”,具体包括:
  • ​分类统计​​:按消费类型(如餐饮、交通、购物)自动分类,通过图表(饼图/柱状图)展示各类别的消费金额占比与趋势。
  • ​账单导出​​:将交易记录导出为通用格式(如CSV/Excel),支持分享至其他应用(如微信、邮箱)或本地保存,便于记账软件导入或财务对账。
  • ​数据安全​​:交易记录包含敏感信息(如交易金额、商户名称),需确保本地存储加密与用户授权访问。
  • ​交互体验​​:支持按时间筛选(如本月/本年)、搜索商户名称,提升数据查询效率。

2. 鸿蒙的技术能力支撑

鸿蒙系统提供了以下关键能力,助力交易记录可视化实现:
  • ​UI组件库(ArkUI)​​:通过 @ohos.agp.components提供图表组件(如 PieChartColumnChart,需结合第三方库或自定义绘制)和列表组件(ListGrid),支持动态数据绑定与交互事件。
  • ​分布式数据管理​​:通过 @ohos.data.preferences@ohos.data.rdb(关系型数据库)存储交易记录,支持本地加密存储与多设备同步(可选)。
  • ​文件操作与分享​​:通过 @ohos.file.fs管理本地文件(如生成CSV文件),通过 @ohos.app.ability.Share实现账单文件的分享(如发送至微信、邮箱)。
  • ​数据统计与分析​​:通过JavaScript/TypeScript的数组方法(如 reducefilter)对交易记录进行分类汇总,计算各类别的总金额与占比。

3. 常见交易记录可视化形式

可视化类型
实现方式
适用场景
​分类统计图表​
使用饼图展示各消费类别的金额占比,或柱状图展示月度消费趋势。
快速了解消费结构(如餐饮占60%)
​账单列表​
以表格形式展示交易详情(时间、商户、金额、类别),支持筛选与搜索。
查看具体交易记录
​账单导出​
生成CSV/Excel文件,包含交易时间、商户、金额、类别等字段,支持本地保存或分享。
财务对账或记账软件导入

三、应用使用场景

1. 个人日常财务管理

​场景描述​​:用户通过鸿蒙应用记录每日消费(如扫码付款后自动同步交易记录),在月末查看分类统计图表(如“餐饮30%、交通15%、购物55%”),快速定位大额消费类别,调整下月预算。
​适用场景​​:个人用户日常消费记录与分析。

2. 家庭共同账本

​场景描述​​:家庭成员共享一个交易记录账本,应用按成员分类统计消费(如“爸爸餐饮500元、妈妈购物300元”),并通过图表展示家庭整体消费分布,促进合理分配家庭开支。
​适用场景​​:家庭财务管理、共同记账场景。

3. 企业差旅报销

​场景描述​​:员工通过鸿蒙应用记录出差期间的交通、住宿、餐饮等交易,应用自动分类统计差旅费用(如“机票2000元、酒店1500元、餐饮800元”),并导出CSV文件提交至财务系统进行报销审核。
​适用场景​​:企业员工差旅报销、项目费用统计。

4. 商户销售数据分析

​场景描述​​:小微商户通过鸿蒙应用记录每日销售交易(如商品销售、退款),按商品类别(如“服装类5000元、食品类3000元”)统计销售额,通过图表分析热销品类,优化库存管理。
​适用场景​​:个体商户、小型零售店销售管理。

四、不同场景下详细代码实现

场景1:分类统计图表(饼图展示消费占比)

​需求​​:将交易记录按类别(如餐饮、交通、购物)分类,计算各类别的总金额,通过饼图展示占比(使用自定义绘制或第三方图表库)。

4.1 交易记录数据模型(models/Transaction.ets)

// src/main/ets/models/Transaction.ets
export interface Transaction {
  id: string;           // 交易唯一ID
  time: string;         // 交易时间(如 "2025-01-20 14:30")
  merchant: string;     // 商户名称(如 "星巴克")
  amount: number;       // 交易金额(单位:元)
  category: string;     // 消费类别(如 "餐饮"、"交通")
}

4.2 分类统计逻辑(utils/StatisticsUtil.ets)

// src/main/ets/utils/StatisticsUtil.ets
import { Transaction } from '../models/Transaction';

// 按类别统计总金额
export function getCategoryStatistics(transactions: Transaction[]): Map<string, number> {
  const categoryMap = new Map<string, number>();
  transactions.forEach(transaction => {
    const currentAmount = categoryMap.get(transaction.category) || 0;
    categoryMap.set(transaction.category, currentAmount + transaction.amount);
  });
  return categoryMap;
}

// 获取所有消费类别(去重)
export function getCategories(transactions: Transaction[]): string[] {
  return [...new Set(transactions.map(t => t.category))];
}

4.3 饼图组件(components/PieChart.ets)

// src/main/ets/components/PieChart.ets
import { View, Canvas, CanvasRenderingContext2D } from '@ohos.agp.components';
import { getCategoryStatistics } from '../utils/StatisticsUtil';

@Component
export struct PieChart {
  @Prop transactions: Transaction[] = []; // 接收父组件传递的交易记录
  private readonly centerX = 150; // 饼图中心X坐标
  private readonly centerY = 150; // 饼图中心Y坐标
  private readonly radius = 100;  // 饼图半径

  build() {
    Canvas(this.centerX * 2, this.centerY * 2)
      .width('100%')
      .height('300px')
      .onReady(() => {
        this.drawPieChart();
      })
  }

  private drawPieChart() {
    const ctx = getContext(this) as CanvasRenderingContext2D;
    const stats = getCategoryStatistics(this.transactions);
    const categories = Array.from(stats.keys());
    const amounts = categories.map(cat => stats.get(cat)!);
    const total = amounts.reduce((sum, a) => sum + a, 0);

    let currentAngle = -Math.PI / 2; // 起始角度(12点方向)

    categories.forEach((category, index) => {
      const amount = stats.get(category)!;
      const percentage = amount / total;
      const sliceAngle = percentage * 2 * Math.PI;

      // 设置颜色(可根据类别动态分配)
      const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'];
      ctx.fillStyle = colors[index % colors.length];

      // 绘制扇形
      ctx.beginPath();
      ctx.moveTo(this.centerX, this.centerY);
      ctx.arc(this.centerX, this.centerY, this.radius, currentAngle, currentAngle + sliceAngle);
      ctx.closePath();
      ctx.fill();

      // 绘制类别标签(可选)
      const labelAngle = currentAngle + sliceAngle / 2;
      const labelX = this.centerX + Math.cos(labelAngle) * (this.radius * 0.7);
      const labelY = this.centerY + Math.sin(labelAngle) * (this.radius * 0.7);
      ctx.fillStyle = '#000';
      ctx.font = '12px Arial';
      ctx.textAlign = 'center';
      ctx.fillText(`${category} (${(percentage * 100).toFixed(1)}%)`, labelX, labelY);

      currentAngle += sliceAngle;
    });
  }
}

4.4 交易记录页面(pages/TransactionPage.ets)

// src/main/ets/pages/TransactionPage.ets
import { Transaction } from '../models/Transaction';
import { PieChart } from '../components/PieChart';

@Entry
@Component
struct TransactionPage {
  @State transactions: Transaction[] = [
    { id: '1', time: '2025-01-20 14:30', merchant: '星巴克', amount: 35.0, category: '餐饮' },
    { id: '2', time: '2025-01-20 08:00', merchant: '地铁站', amount: 6.0, category: '交通' },
    { id: '3', time: '2025-01-19 20:00', merchant: '万达广场', amount: 299.0, category: '购物' },
    { id: '4', time: '2025-01-19 12:30', merchant: '肯德基', amount: 45.0, category: '餐饮' },
  ];

  build() {
    Column() {
      Text('交易记录分类统计')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 20 });

      // 饼图展示分类统计
      PieChart({ transactions: this.transactions })

      // 交易列表(可选)
      List() {
        ForEach(this.transactions, (transaction: Transaction) => {
          ListItem() {
            Row() {
              Text(transaction.time.substring(5, 10)) // 显示日期(如01-20)
                .fontSize(14)
                .width('15%');
              Text(transaction.merchant)
                .fontSize(14)
                .width('30%');
              Text(`¥${transaction.amount.toFixed(2)}`)
                .fontSize(14)
                .fontColor(Color.Red)
                .width('20%');
              Text(transaction.category)
                .fontSize(14)
                .width('25%');
            }
            .width('100%')
            .padding(10);
          }
        })
      }
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .padding(20);
  }
}

4.5 原理解释

  • ​数据模型​​:Transaction接口定义了交易记录的核心字段(时间、商户、金额、类别),用于存储和传递交易数据。
  • ​分类统计逻辑​​:getCategoryStatistics函数遍历交易记录,按 category字段分组并累加金额,返回一个 Map<string, number>(键为类别,值为该类别总金额)。
  • ​饼图绘制​​:PieChart组件通过Canvas API自定义绘制饼图,根据各类别的金额占比计算扇形角度(sliceAngle = (amount / total) * 2π),并使用不同颜色区分类别,同时在扇形中心标注类别名称和占比。
  • ​组件集成​​:交易记录页面(TransactionPage)将交易数据通过 @State管理,并将 transactions数组传递给 PieChart组件进行可视化展示,同时通过 List组件展示原始交易列表(可选)。

场景2:账单导出(生成CSV文件并分享)

​需求​​:用户点击“导出账单”按钮后,应用将当前交易记录生成CSV格式文件(包含时间、商户、金额、类别字段),并调用鸿蒙的文件分享功能,支持保存至本地或分享至其他应用(如微信、邮箱)。

4.6 CSV生成工具(utils/CsvUtil.ets)

// src/main/ets/utils/CsvUtil.ets
import { Transaction } from '../models/Transaction';

// 生成CSV内容(首行为表头,后续为交易记录)
export function generateCsvContent(transactions: Transaction[]): string {
  const headers = ['时间', '商户', '金额(元)', '类别'];
  const rows = transactions.map(t => [t.time, t.merchant, t.amount.toFixed(2), t.category]);
  return [headers, ...rows].map(row => row.join(',')).join('\n');
}

// 保存CSV文件到本地并返回文件路径
export async function saveCsvFile(content: string, fileName: string = '交易账单.csv'): Promise<string> {
  try {
    // 获取应用文档目录(鸿蒙提供的全局存储路径)
    const documentDir = await getDocumentDir();
    const filePath = `${documentDir}/${fileName}`;

    // 写入文件内容
    await writeFile(filePath, content, { encoding: 'utf-8' });
    return filePath;
  } catch (error) {
    console.error('保存CSV文件失败:', error);
    throw new Error('文件保存失败');
  }
}

// 鸿蒙文件操作辅助函数(简化示例,实际需使用 @ohos.file.fs)
async function getDocumentDir(): Promise<string> {
  // 实际项目中应调用鸿蒙的文件API获取文档目录(如 context.getFilesDir())
  return '/data/accounts/appdata/documents'; // 示例路径(需替换为真实路径)
}

async function writeFile(path: string, content: string, options: { encoding: string }): Promise<void> {
  // 实际项目中应使用 @ohos.file.fs.writeFile 实现文件写入
  console.log(`模拟写入文件: ${path}, 内容: ${content.substring(0, 50)}...`);
  // 此处为模拟逻辑,真实环境需调用鸿蒙文件API
}

4.7 账单导出页面(pages/ExportPage.ets)

// src/main/ets/pages/ExportPage.ets
import { Transaction } from '../models/Transaction';
import { generateCsvContent, saveCsvFile } from '../utils/CsvUtil';
import { BusinessError } from '@ohos.base';

@Entry
@Component
struct ExportPage {
  @State transactions: Transaction[] = [
    { id: '1', time: '2025-01-20 14:30', merchant: '星巴克', amount: 35.0, category: '餐饮' },
    { id: '2', time: '2025-01-20 08:00', merchant: '地铁站', amount: 6.0, category: '交通' },
    { id: '3', time: '2025-01-19 20:00', merchant: '万达广场', amount: 299.0, category: '购物' },
  ];

  async handleExport() {
    try {
      // 1. 生成CSV内容
      const csvContent = generateCsvContent(this.transactions);
      
      // 2. 保存CSV文件到本地
      const filePath = await saveCsvFile(csvContent, '我的交易账单.csv');
      console.log(`CSV文件已保存至: ${filePath}`);

      // 3. 调用鸿蒙分享功能(分享文件或直接打开)
      await this.shareFile(filePath);
      
      // 提示用户
      alert('账单导出成功!文件已保存并可分享。');
    } catch (error) {
      console.error('导出失败:', error);
      alert('导出失败,请重试。');
    }
  }

  // 鸿蒙文件分享功能(简化示例,实际需使用 @ohos.app.ability.Share)
  private async shareFile(filePath: string) {
    // 实际项目中应调用鸿蒙的分享API(如 Share.shareFile(filePath))
    console.log(`模拟分享文件: ${filePath}`);
    // 此处为模拟逻辑,真实环境需调用鸿蒙分享API
  }

  build() {
    Column() {
      Text('账单导出')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 30 });

      Button('导出CSV账单')
        .width('80%')
        .height(50)
        .fontSize(16)
        .onClick(() => {
          this.handleExport();
        })
        .margin({ bottom: 20 });

      Text('导出内容包含:交易时间、商户、金额、类别')
        .fontSize(14)
        .fontColor(Color.Gray);
    }
    .width('100%')
    .height('100%')
    .padding(20)
    .justifyContent(FlexAlign.Center);
  }
}

4.8 原理解释

  • ​CSV生成​​:generateCsvContent函数将交易记录数组转换为CSV格式字符串(首行为表头 时间,商户,金额(元),类别,后续每行为一条交易的字段值,用逗号分隔)。
  • ​文件保存​​:saveCsvFile函数模拟将CSV内容写入本地文件(实际需调用鸿蒙的 @ohos.file.fs.writeFileAPI),文件默认保存至应用的文档目录(如 /data/accounts/appdata/documents/我的交易账单.csv)。
  • ​文件分享​​:shareFile函数模拟调用鸿蒙的分享能力(实际需使用 @ohos.app.ability.Share模块),用户可选择将文件保存至本地相册/文件管理器,或直接分享至微信、邮箱等应用。

五、原理解释

1. 交易记录可视化的核心流程

  1. ​数据管理​​:交易记录以结构化数据(Transaction对象数组)的形式存储在应用内存或本地数据库(如 @ohos.data.rdb),包含时间、商户、金额、类别等字段。
  2. ​分类统计​​:通过JavaScript的数组方法(如 reducefilter)或自定义工具函数(如 getCategoryStatistics),按 category字段分组并计算各类别的总金额,生成统计结果(如 { 餐饮: 80.0, 交通: 6.0, 购物: 299.0 })。
  3. ​可视化展示​​:分类统计结果通过自定义Canvas绘制(如饼图)或第三方图表库(如ECharts for HarmonyOS)呈现,直观展示各类别的消费占比;交易列表通过 List组件展示原始数据,支持筛选与搜索。
  4. ​账单导出​​:将交易记录转换为通用格式(如CSV),通过文件操作API(如 @ohos.file.fs)生成本地文件,并调用鸿蒙的分享能力(如 @ohos.app.ability.Share)实现文件保存或跨应用分享。

2. 关键技术点

  • ​Canvas绘图​​:通过 Canvas组件和 CanvasRenderingContext2DAPI自定义绘制饼图/柱状图,灵活控制图表样式与交互(如颜色分配、标签显示)。
  • ​文件操作​​:使用鸿蒙的文件系统API(如 writeFile)管理本地文件,确保交易记录数据的安全存储与导出。
  • ​数据转换​​:将结构化数据(JSON/对象数组)转换为通用格式(CSV/Excel),兼容外部记账软件或财务工具的数据导入需求。

六、核心特性

特性
说明
​分类统计可视化​
通过饼图/柱状图直观展示各消费类别的金额占比与趋势,支持动态数据更新。
​账单导出功能​
生成CSV/Excel格式文件,支持本地保存与跨应用分享(如微信、邮箱)。
​数据安全​
交易记录存储在应用私有目录或加密数据库,确保敏感信息不被泄露。
​交互筛选​
支持按时间范围(如本月/本年)、商户名称搜索交易记录,提升查询效率。
​多场景适配​
适用于个人财务管理、家庭账本、企业差旅报销等不同需求场景。

七、原理流程图及原理解释

原理流程图(交易记录可视化执行流程)

+-----------------------+       +-----------------------+       +-----------------------+
|  用户查看交易记录    |       |  分类统计计算         |       |  可视化展示(饼图)   |
|  (点击“账单”页面)    | ----> |  (按类别分组求和)     | ----> |  (Canvas绘制占比)    |
+-----------------------+       +-----------------------+       +-----------------------+
          |                             |                             |
          |  数据源:交易记录   |  生成统计结果         |  显示各类别消费占比   |
          |  (时间/商户/金额)  |  (如餐饮:80元)        |  (饼图扇形+标签)      |
          v                             v                             v
+-----------------------+       +-----------------------+       +-----------------------+
|  用户点击“导出账单”  |       |  生成CSV文件          |       |  文件分享/保存        |
|  (点击导出按钮)      | ----> |  (时间/商户/金额/类别)| ----> |  (本地存储/微信分享) |
+-----------------------+       +-----------------------+       +-----------------------+

原理解释

  1. ​数据准备​​:用户打开交易记录页面,应用从本地存储(如数据库或内存数组)加载交易记录数据(包含时间、商户、金额、类别)。
  2. ​分类统计​​:通过工具函数(如 getCategoryStatistics)对交易记录按 category字段分组,计算每个类别的总金额(如餐饮类总和为80元),生成统计结果(Map<string, number>)。
  3. ​可视化渲染​​:分类统计结果传递给自定义的 PieChart组件,通过Canvas API绘制饼图——根据各类别金额占比计算扇形角度(如餐饮占比20%,则扇形角度为20%×360°),并用不同颜色区分类别,同时在扇形中心标注类别名称和百分比。
  4. ​账单导出​​:用户点击“导出账单”后,应用将交易记录转换为CSV格式字符串(包含表头和每行交易数据),通过文件操作API将内容写入本地文件(如 /documents/我的交易账单.csv),并调用鸿蒙的分享能力(如 Share.shareFile),支持用户将文件保存至本地或分享至其他应用(如微信、邮箱)。

八、环境准备

1. 开发环境

  • ​工具​​:DevEco Studio(鸿蒙官方IDE,基于IntelliJ IDEA),Node.js(≥14),HarmonyOS SDK(版本 ≥ 3.2,支持Canvas和文件API)。
  • ​设备​​:搭载鸿蒙OS 3.0及以上的设备(如华为P50、Mate 50),用于真机测试账单导出和分享功能。

2. 项目初始化

# 使用DevEco Studio创建新项目(选择“Empty Ability”模板)
# 配置交易记录数据模型(models/Transaction.ets)和工具函数(utils/StatisticsUtil.ets、utils/CsvUtil.ets)

3. 权限配置

若涉及文件读写或分享功能,需在 config.json中声明以下权限(根据实际需求调整):
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.READ_MEDIA",
        "reason": "用于读取交易记录相关媒体文件(如有图片凭证)"
      },
      {
        "name": "ohos.permission.WRITE_MEDIA",
        "reason": "用于保存导出的账单文件"
      }
    ]
  }
}

九、实际详细应用代码示例实现

完整代码结构(基于场景1~2)

  • ​数据模型​​(models/Transaction.ets):定义交易记录的结构(时间、商户、金额、类别)。
  • ​统计工具​​(utils/StatisticsUtil.ets):提供分类统计和类别提取的逻辑。
  • ​图表组件​​(components/PieChart.ets):自定义Canvas绘制饼图,展示消费占比。
  • ​导出工具​​(utils/CsvUtil.ets):生成CSV文件内容并保存至本地。
  • ​页面集成​​(pages/TransactionPage.etspages/ExportPage.ets):展示交易列表与分类统计图表,提供账单导出功能。
​运行步骤​​:
  1. 使用DevEco Studio创建鸿蒙项目,按照代码示例实现各模块。
  2. 在模拟器或真机上运行应用,添加测试交易记录,查看分类统计饼图和交易列表。
  3. 点击“导出账单”按钮,验证CSV文件是否生成并支持分享/保存。

十、运行结果

正常情况(功能生效)

  • ​分类统计​​:饼图清晰展示各消费类别的占比(如餐饮30%、交通15%、购物55%),鼠标悬停(或点击)可查看具体金额。
  • ​账单导出​​:点击“导出账单”后,生成包含交易时间、商户、金额、类别的CSV文件,支持保存至本地或分享至微信/邮箱。
  • ​交互体验​​:交易列表支持滚动查看,分类统计图表响应式适配不同屏幕尺寸。

异常情况(功能未生效)

  • ​图表未渲染​​:检查 PieChart组件是否正确接收交易数据,或Canvas绘制逻辑是否有误(如坐标计算错误)。
  • ​文件保存失败​​:确认文件路径权限(如应用是否有写入文档目录的权限),或 writeFile模拟逻辑是否替换为真实API。
  • ​分享无响应​​:检查鸿蒙分享API(如 @ohos.app.ability.Share)是否正确调用,或设备是否支持文件分享功能。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。