编写属于你自己的账单小组件

Cent 1.5引入了全新的 Widget 系统,允许你用一小段 JavaScript 脚本读取账本数据、渲染轻量 UI,并通过配置表单把组件参数暴露给最终用户。本文面向开发者和高级用户,介绍 Widget 能做什么、权限与数据模型、如何编写最小可运行示例,以及在 Cent 编辑器里调试与发布的实用步骤。

为什么要用 Widget?

  • 可视化你关心的统计:自定义支出聚合、分类排行、预算进度等。

  • 轻量而安全:DSL 渲染(Flex / Text / Container 等)避免直接操作 DOM,执行环境做了权限与 API 限制。

  • 用户可配置:通过 export const config 自动生成表单,让非开发者也能调整展示参数。

核心概念速览

  • 元数据与权限:通过文件头部的 JSDoc 注释声明 @widget-api@name@permissions,未声明的权限在运行时将不会注入对应数据。

  • config:导出对象,用于定义配置表单(支持 textnumberdateselect)。

  • 渲染函数:脚本必须默认导出一个 async 函数,签名为 async (context) => DSL,接收 context.datacontext.settingscontext.env

  • DSL:使用 FlexTextContainer 等链式 API 返回 UI 描述,由 Cent 内部渲染为真实 React 组件。

更多技术细节与权限表请参见仓库内的规范:src/components/widget/core/WIDGET_API.md

最小可运行示例 下面的示例展示了一个简单的“账单总额”组件:它声明了 billing 权限、定义了一个可配置的标题,并在渲染函数中从 context.data.billing 计算总额。

javascript
/**
 * @widget-api 1.0
 * @name 账单总额(示例)
 * @permissions billing
 */

export const config = {
  title: { type: 'text', label: '标题', default: '我的账单总额' },
  startDate: { type: 'date', label: '开始日期' }
};

export default async ({ data, settings, env }) => {
  const bills = (data && data.billing) || [];
  const start = settings.startDate ? new Date(settings.startDate) : null;
  const filtered = start ? bills.filter(b => new Date(b.time) >= start) : bills;
  const total = filtered.reduce((s, b) => s + (b.amount || 0), 0);

  return Flex(
    Text(settings.title || '账单总额').fontSize(16).bold(),
    Text('总金额:' + total).fontSize(14).color('#333')
  ).direction('column').gap(8);
};

如何在 Cent 编辑器中调试(3 步)

  1. 打开 设置 → Widget 设置,点击“新增 Widget”或编辑已有 Widget,粘贴上面的代码。

  2. 在编辑器右侧的权限栏勾选 billing(若编辑器提示需要),在表单区填写 startDate 或保留默认值。

  3. 观察预览区,编辑器会在你修改后约 500ms 防抖后自动运行并更新预览;若出错,编辑器会显示错误信息与堆栈,方便定位。

关于权限与数据 Widget 的数据注入严格根据头部注释声明的权限提供。例如声明 @permissions billing, category 将允许你的脚本通过 context.data.billingcontext.data.categories 访问账单与分类数据。出于安全与稳定性考虑,运行时会剥离潜在危险的全局 API(如 eval / Function / 网络套接字)。详情见规范文档: src/components/widget/core/WIDGET_API.md

实用提示与常见坑

  • 保持渲染函数为纯函数:不要在运行时修改外部状态或调用长时阻塞的网络请求(渲染超时为 2000ms)。

  • 使用 settings 提供灵活性:尽量将可变参数放在 config 中,让最终用户能通过表单调整行为。

  • 对数据做稳健判断:context.data 中的字段可能为 undefined(未授权),请使用默认值以避免运行时错误。

发布与在首页展示 编辑器中保存并启用 showInHome(或在 Widget 列表中切换开关),已启用的 Widget 会出现在首页(src/pages/home/index.tsx),以横向滑动容器的形式显示,用户可通过滑动或切换查看多个 Widget。

Widget API 为 Cent 提供了一条平衡灵活性与安全性的可扩展路径:开发者可以用熟悉的 JavaScript 定制数据展示,而普通用户能通过自动生成的表单调整参数并实时预览效果。