文章 文章 posts

Strapi 个人账本系统设计

本文介绍如何使用 Strapi 设计一个简单的个人账本系统,满足以下需求:

需求分析

  1. 用户(User)

    • 用户可以注册、登录
    • 系统默认使用 Strapi 自带的用户管理
  2. 类别(Category)

    • 用户可以新建、编辑、删除自己的类别
    • 示例类别:吃饭、教育
    • 每个类别只能归属于创建者
  3. 类型(Type)

    • 系统固定:收入(Income)和支出(Expense)
    • 不允许用户修改或删除
  4. 入账记录(Transaction)

    • 记录金额、类别、类型和日期
    • 用户只能操作自己的记录

数据模型设计

用户(User)

Strapi 默认提供:

  • username
  • email
  • password

无需额外建表。

类型(Type)

系统固定枚举:

  • Collection Name: Type
  • 字段:
    • name(枚举):income / expense
  • 系统初始化时创建两条数据
  • 只读,不允许用户修改

类别(Category)

用户自定义:

  • Collection Name: Category
  • 字段:
    • name(string):类别名称
    • user(relation):User → Category(many-to-one)
  • 权限:
    • 用户只能操作自己的类别
    • 查询只返回自己的类别

入账记录(Transaction)

记录每笔账目:

  • Collection Name: Transaction
  • 字段:
    • amount(number):金额
    • category(relation):Category → Transaction(many-to-one)
    • type(relation):Type → Transaction(many-to-one)
    • user(relation):User → Transaction(many-to-one)
    • date(date):日期,默认当前时间
    • note(string,可选):备注
  • 权限:
    • 用户只能查看、编辑、删除自己的交易
    • type 只能选择系统已有的“收入/支出”

权限控制

  1. Category

    • 创建、更新、删除:仅允许自己操作
    • 查询:仅返回自己的数据
  2. Transaction

    • 创建、更新、删除:仅允许自己操作
    • 查询:仅返回自己的数据
  3. Type

    • 只读,所有用户可查询

Strapi 实现细节

枚举类型

在 Transaction 中可直接使用枚举:

json
{
  "type": "enumeration",
  "enum": ["income", "expense"]
}

`

Policy 示例(限制用户操作自己的类别)

js
// ./src/policies/isOwner.js
module.exports = async (ctx, next) => {
  const { id } = ctx.params;
  const entity = await strapi.db.query('api::category.category').findOne({ where: { id } });
  if (!entity || entity.user.id !== ctx.state.user.id) {
    return ctx.unauthorized('You can only access your own data');
  }
  await next();
};

系统初始化

  1. 创建 Type 数据:

    • income
    • expense
  2. 用户注册后,可创建自己的 Category

数据访问示例

查询用户交易

js
const transactions = await strapi.db.query('api::transaction.transaction').findMany({
  where: { user: { id: ctx.state.user.id } },
  populate: ['category', 'type']
});

创建交易

js
await strapi.db.query('api::transaction.transaction').create({
  data: {
    amount: 100,
    category: 1,  // 自己的 category id
    type: 1,      // income 或 expense id
    user: ctx.state.user.id
  }
});

这样就完成了一个 基于 Strapi 的个人账本系统设计,实现了用户注册、类别管理、入账记录及收入/支出类型控制。

Related 工具组件将在独立客户端岛中继续迁移。