news 2026/9/4 23:59:25

开源低代码平台ToolJet实战:快速构建企业内部管理后台

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
开源低代码平台ToolJet实战:快速构建企业内部管理后台

企业内部经常会出现这样的需求:运营需要一个数据看板,测试需要一批测试账号管理页面,客服需要查询用户订单,财务需要核对账单状态。这类系统通常功能不算复杂,但“麻雀虽小五脏俱全”,如果每一套都由开发从头搭建,从登录权限到前端表单再到后端查询,少则一两周,多则一两个月。而这类工具的使用频率和业务价值又非常高,一旦做得不好,企业内部流程就会卡在“信息不透明”上。ToolJet 就是围绕这个痛点出现的开源低代码平台,它把数据源接入、界面搭建、查询逻辑和权限控制统一放进一个可视化工作台里,让开发者和业务人员都能快速搭建内部系统。本文会带你完整理解 ToolJet 的核心概念,完成从部署到搭建一个实用管理后台的全过程,并整理自托管运行时最常见的排错经验与工程建议。

作为一篇偏实战的教程,我更关注怎么把 ToolJet 跑起来,而不是停留在“它能做什么”的功能清单。读完本文后,你可以掌握 ToolJet 的部署方式,理解数据源、查询、组件、事件和数据绑定之间的关系,并且能亲手做出一个基于 PostgreSQL 的员工数据管理面板,包括员工列表、关键字筛选、新增记录、删除记录和部门统计图表。如果你之前没有接触过低代码平台,文章也会先解释它和传统开发的区别,保证零基础也能跟上操作步骤。

1. ToolJet 是什么

1.1 内部系统研发的痛点

大多数公司都不会把内部业务系统当成对外产品来打磨,但这不代表它们不重要。一个运营团队每天需要的数据,往往散落在多个数据库、表格和第三方系统里;研发同学如果把时间都花在重复开发内部后台,核心业务迭代就会被拖慢;如果直接给业务人员一个 SQL 客户端,又不够安全,也不够直观。

传统开发模式要解决的问题其实很清楚:连接数据、写查询逻辑、做展示页面、加权限控制、部署上线。问题是这套流程太重了。每个内部工具都需要工程初始化、目录结构、前后端联调、环境配置,可能还要考虑 Docker 镜像和服务器资源。当需求数量变多,这种重流程会让内部工具的需求排期越来越长。

低代码平台的价值,就是把“页面层”和“数据层”中间的重复工作抽象掉。ToolJet 正是这样一类工具:它并不消灭代码,而是把代码的位置从“写一个完整 Web 应用”收敛到“写一个查询片段”或“写一段数据转换函数”。团队可以在很短时间内从需求澄清走到可用的原型,再通过平台的自托管能力把它变成生产可用的系统。

1.2 ToolJet 的定义

ToolJet 是一个开源的低代码平台,主要用来快速构建企业内部工具。你可以在浏览器中通过拖拽组件的方式搭建页面,也可以连接 MySQL、PostgreSQL、MongoDB、REST API、Google Sheets 等常见数据源,然后编写 SQL 或 API 请求完成数据查询与写入。最终页面可以发布给团队成员,并按照角色分配访问权限。

换句话说,ToolJet 尝试把“后台管理页面”的开发过程变得更像拼装积木。开发者不再需要从零创建 Spring Boot 或 Node.js 服务,也不需要在自己的项目里维护前端表格组件,而是把 Table、Form、Chart、Modal 等可视化组件拖到画布上,再用表达式与查询结果绑定起来。ToolJet 也和传统代码生成器不同,它并不是生成一套代码让你拿走去部署,而是直接运行平台本身,让应用跑在 ToolJet 的服务中。

由于 ToolJet 是开源且支持自托管的,它对数据私密性要求较高的团队非常友好。你可以把 ToolJet、它的数据库以及所有业务数据源都部署在自有机房或云服务器中,降低第三方 SaaS 带来的数据出境顾虑。

1.3 ToolJet 适合哪些人和场景

ToolJet 的目标用户并不是完全不懂技术的业务人员,而是有一定数据处理经验,但又不希望每次都用全套工程化流程去开发内部系统的开发者。后端工程师可以用它快速搭建给运营使用的查询后台,数据分析师可以用它创建自己的数据筛选界面,运维工程师也可以用 ToolJet 做一个简单的配置管理平台。

比较适合 ToolJet 的场景通常有几个共同特点:第一,功能以数据“增删改查”为主,不需要复杂度特别高的状态机;第二,页面交互集中在表格、表单、下拉框、弹窗和图表这些常见组件上;第三,用户量不大,几十到几百人使用即可满足需求;第四,迭代速度快,可能下周就要调整字段或增加新的查询条件。

但 ToolJet 不适合用来做面向海量用户的高并发 C 端系统。你仍然需要专业后端服务来处理复杂权限、性能优化和业务一致性。ToolJet 的定位是提高内部工具的研发效率,而不是替代所有后端开发技术。

1.4 ToolJet 的典型应用场景

在我接触过的项目中,ToolJet 最常用的几类场景包括:运营数据看板,比如把数据库中的订单、用户、渠道数据以表格和图表形式集中展示;后台管理界面,比如用户管理、优惠券配置、Content 内容上下架;数据修复工具,比如由研发或 DBA 输入条件后批量更新线上数据的操作页;接口联调面板,把需要访问的第三方 API 统一封装成可控查询,并在页面上快速验证结果。

一个典型页面可能长这样:顶部是筛选条件,中间是统计卡片或图表,下方是明细数据表格。传统开发这套页面需要写前端列表页、封装接口、处理查询参数、考虑分页问题;而在 ToolJet 中,只需要把 SQL 查询写好,把 Table 组件拖进画布,再绑定数据即可。如果你熟悉 SQL 和 JavaScript,会把 ToolJet 的使用效率再提升一个数量级。

2. ToolJet 的核心概念拆解

2.1 数据源与查询:一切页面的数据入口

在 ToolJet 中,“数据源”代表一个你已经配置好的连接目标,比如一台 PostgreSQL 实例、一个 MySQL 库、一个 MongoDB 集合,或者一个可供访问的 REST API。数据源配置是一次性的,一个数据源可以被多个查询复用。这样配置的好处是,当数据库连接地址发生变化时,你只需要修改数据源,不用逐页修改组件。

“查询”则是在某个数据源上执行的操作。对数据库来说,查询可以是一条 SQL;对 API 来说,查询可以是一个 HTTP 请求。ToolJet 会保存查询定义,你可以随时手动运行它,也可以在页面按钮或组件事件中自动触发它。查询返回的数据会被保存为查询结果,供 Table、Chart、Dropdown 等组件绑定。

这里尤其需要区分两个数据库概念:ToolJet 自身元数据库和业务数据库。ToolJet 服务端本身需要一个数据库来保存应用定义、用户账号、查询配置和页面快照等信息;而你在数据源里配置的业务数据库,才是页面要操作的真实业务数据。日常维护时不要把两者混为一谈,尤其是执行备份和权限清理时,要分别对待。

2.2 组件与数据绑定:了解双花括号表达式

ToolJet 的界面由各种可视化组件组成,包括文本、按钮、表格、输入框、下拉选择器、日期选择器、Modal 弹窗、图表、容器等。每个组件都可以重命名,并拥有一组可配置的属性。为了让页面真正驱动起来,我们需要把组件产生的值和查询返回的数据连接起来,这个动作就叫数据绑定。

ToolJet 最常见的绑定语法是双花括号{{ }}。你会在属性面板中填写类似下面的表达式:

{{queries.getEmployees.data}}

它的含义是:将getEmployees这个查询返回的数据,绑定到当前组件的某个属性上。如果绑定到 Table 的 Data 属性,表格就会显示查询结果;如果绑定到 Text 的 Content 属性,页面就会输出数据内容。

除了查询数据,组件的值也能被读取。比如我们把一个文本输入框命名为searchInput,后续就可以通过{{searchInput.value}}拿到用户输入的内容。又比如绑定 Table 的选中行属性,可以使用{{employeeTable.selectedRow.id}}拿到当前选中记录的主键。理解这一层,就能玩转 ToolJet 的交互逻辑。

这里补充一个新手最常见的误区:在 ToolJet 的表达式里,组件名和查询名要尽量使用英文字母、数字和下划线,如果用中文命名,不少表达式解析版本会报错或者在某些渲染环境下出现编码问题。后续所有示例我都会采用英文命名。

2.3 事件处理器与页面发布机制

组件只是静态展示还不够,ToolJet 想要完成业务流程,还需要“事件处理器”。事件处理器是页面交互逻辑的核心入口,比如用户点击按钮后发生什么、查询成功后发生什么、Modal 关闭后发生什么。我们可以为按钮配置事件:点击按钮时运行某个查询、打开弹窗、展示提示、刷新某个查询。

一个比较常见的设计是:点击“保存”按钮,先运行insertEmployee查询,数据插入成功后,再运行getEmployees查询刷新表格。这样页面上的操作顺序就变成了:用户操作组件 -> 触发事件 -> 执行查询 -> 绑定数据刷新界面。

ToolJet 的应用页面分为编辑态、预览态和已发布状态。编辑态用于开发调试,预览态让你在发布前检查体验,已发布状态才会被普通成员看到。在实际开发中,建议把页面搭建完成并验证查询绑定正确后,再点击发布。发布后的地址可以分享给其他团队成员,ToolJet 会按照账号权限决定谁能访问、谁能编辑、谁能查看。

3. ToolJet 环境准备与自托管部署

3.1 部署方式选择

使用 ToolJet 有两种主流方式。第一种是使用官方托管的云服务,注册后可以直接创建 Workspace 开始搭建应用,适合想快速验证产品能力和不想维护服务器的小团队。第二种是自托管,把 ToolJet 的 Docker 镜像部署到自己的服务器上,适合对数据安全、私网连接和定制化要求更高的团队。

本文重点介绍自托管方式。自托管带来的好处是数据完全在自己环境内流转,但同样意味着你需要承担运维责任,比如数据库备份、镜像升级、访问日志监控和系统资源观察。如果团队没有专职运维,建议先在一台配置足够的 Linux 服务器上运行,并且一定要预留数据卷备份目录。

开始前你需要准备一台 Linux 服务器或本地虚拟机,建议系统内存不低于 4GB,磁盘空间根据内部工具数量预留至少 20GB。服务器需要安装 Docker 和 Docker Compose。以下安装步骤以常见环境为例,不同操作系统细节会有差异,重点演示配置思路,请以你的实际环境版本为准。

3.2 使用 Docker Compose 快速部署

为了把 ToolJet 自身的元数据库和应用服务一起管理起来,我们使用 Docker Compose 定义两个服务:ToolJet 主服务和 PostgreSQL 元数据库。以下是最小化的部署示例:

# 文件路径:docker-compose.yml version: "3" services: tooljet: image: trytooljet/tooljet:latest restart: unless-stopped ports: - "8080:8080" environment: TOOLJET_DB_HOST: postgres TOOLJET_DB_USER: tooljet TOOLJET_DB_PASSWORD: change_me_strong_password TOOLJET_DB_NAME: tooljet # 认证加密相关密钥,建议用 openssl rand -hex 32 生成 # SECRET_KEY_BASE: <random> # LOCKBOX_MASTER_KEY: <random> depends_on: - postgres postgres: image: postgres:14 restart: unless-stopped environment: POSTGRES_USER: tooljet POSTGRES_PASSWORD: change_me_strong_password POSTGRES_DB: tooljet volumes: - tooljet_pgdata:/var/lib/postgresql/data volumes: tooljet_pgdata:

这里需要特别提醒,部署演示中我把一部分环境变量按常见写法列了出来,但不同版本对密钥变量和初始化参数的命名可能存在差异。实际生产环境请直接参考官方最新的 docker-compose 模板和 release release 文档,不要照抄后直接上线。尤其要注意把change_me_strong_password和注释中的随机密钥替换成足够长的随机内容。

启动命令比较简单:

docker compose up -d

启动过程首次会拉取镜像并初始化数据库,可能需要等待几分钟。运行以下命令观察日志:

docker compose logs -f tooljet

当你看到 ToolJet 输出服务启动成功的日志后,打开浏览器访问http://服务器IP:8080,即可进入 ToolJet 的初始化页面。

3.3 初始化与运维要点

首次进入 ToolJet 页面时,你需要根据系统提示创建管理员账号,然后进入工作台。后续添加团队成员的方式也是通过平台的内置账号管理功能完成。管理员账号拥有全部权限,可以管理组织内成员、创建数据源、编辑应用和发布应用。

日常运维有几个关键点必须注意。

第一,密钥和数据库密码一定要保存好,尤其是加密密钥一旦丢失,可能导致已有会话和应用加密数据无法解密,恢复过程会非常痛苦。建议把密钥放到独立的.env文件中,并确保该文件不会被提交到代码仓库。

第二,要定期备份 PostgreSQL 元数据库。ToolJet 的应用页面结构、查询定义都保存在元数据库中,业务数据反而不会存进来。你可以通过 PostgreSQL 的pg_dump工具或者云数据库自带备份功能执行备份,工具核心配置才不会因服务器故障丢失。

第三,镜像升级前先查看官方更新说明。ToolJet 迭代速度较快,升级可能带来数据库结构迁移或配置项调整。建议先在测试环境完成一次完整升级,再对生产环境操作。升级前一定要备份元数据库和.env配置文件。

4. 实战:用 ToolJet 搭建员工数据管理面板

4.1 需求分析与数据表准备

为了把前面的概念串起来,这一节我们实现一个非常典型的企业内部管理页面:员工数据管理面板。业务需求如下:能查看员工列表,能按关键字筛选姓名或部门,能新增员工,能删除选中的员工,还能按部门统计员工人数。整个场景没有复杂的业务流程,很适合用 ToolJet 来演示。

先准备一张简单的 PostgreSQL 员工表。为了减少环境依赖,我们在 ToolJet 连接的业务 PostgreSQL 数据库中执行以下 SQL:

-- 创建员工示例表 CREATE TABLE IF NOT EXISTS employees ( id SERIAL PRIMARY KEY, name VARCHAR(50) NOT NULL, department VARCHAR(50) NOT NULL, email VARCHAR(100), status VARCHAR(20) DEFAULT 'active', created_at TIMESTAMP DEFAULT NOW() ); -- 插入几条示例数据 INSERT INTO employees (name, department, email, status) VALUES ('张明', '研发部', 'zhangming@example.com', 'active'), ('李华', '运营部', 'lihua@example.com', 'active'), ('王强', '数据部', 'wangqiang@example.com', 'inactive'), ('赵敏', '市场部', 'zhaomin@example.com', 'active'), ('刘洋', '研发部', 'liuyang@example.com', 'active');

这里使用SERIAL自增主键,创建时间默认使用当前时间。项目中使用 PostgreSQL 14 及以上版本均可。你完全可以把表结构换成自己业务中的订单表、商品表或审计日志表,核心思路是一样的。

4.2 在 ToolJet 中配置 PostgreSQL 数据源

进入 ToolJet 工作台后,先创建一个新的应用。在应用编辑区左侧找到数据源管理入口,选择 PostgreSQL,然后填写数据库连接信息。这里的数据库地址要填写你的业务 PostgreSQL 可访问的地址,用户名建议使用只读和可写权限分离的账号,并根据实际需要限制访问。

ToolJet 通常会提供 Test Connection 按钮,点击后显示连接成功,说明配置无误。连接成功后,我们可以创建第一个查询,命名为getEmployees,数据源选择刚才创建的 PostgreSQL 数据源,查询内容为:

SELECT id, name, department, email, status, created_at FROM employees ORDER BY created_at DESC;

点击 Run 按钮执行查询,如果下方展示出刚刚插入的 5 条数据,说明查询链路已经打通。这个查询用于加载表格初始数据,后续组件中的 Table 会直接绑定它的返回结果。

为了支持前端关键字搜索,我们还可以在查询中添加一个 JavaScript Transformations。ToolJet 的 Transformations 允许在查询结果展示到组件之前做一次数据处理。我们在该查询的 Transformations 区域写入:

// 将查询返回的 data 根据搜索框输入进行过滤 const keyword = String(searchInput.value || '').trim().toLowerCase(); if (!keyword) { return data; } return data.filter((item) => [item.name, item.department, item.email, item.status] .join(' ') .toLowerCase() .includes(keyword) );

这段代码会读取页面上名为searchInput的输入框组件内容。如果搜索框为空,就返回原始数据;如果用户输入了关键字,就按姓名、部门、邮箱、状态做一次前端过滤。这样搜索不需要反复请求数据库,适合当前这种数据量不大的内部工具场景。

4.3 搭建页面组件并绑定数据

回到应用画布,我们开始搭建界面。在组件库中选中 Table 组件并拖入画布,将组件重命名为employeeTable。在 Table 组件的属性面板中,找到 Data 字段并填入:

{{queries.getEmployees.data}}

保存后进入预览,表格应该能自动根据查询结果渲染出idnamedepartment等列。如果列没有自动生成,可以通过 Table 的 Column Definition 手动维护列,并将字段名与 SQL 返回字段保持一致。

接下来在页面顶部放入一个文本输入框,重命名为searchInput,并在它的 onChange 事件中绑定一个动作:运行查询getEmployees。这样用户每次输入关键字并触发变更后,Transformations 会重新读取搜索内容,前端表格数据也就同步更新了。再往页面中放入两个按钮:openAddModalBtn用于打开新增员工弹窗,deleteEmployeeBtn用于删除当前表格选中的员工。

组件全部放入后,可以借助右侧的组件树检查命名是否清晰:employeeTablesearchInputopenAddModalBtndeleteEmployeeBtnsaveEmployeeBtn。准确命名虽然不影响功能,但能让后续合作维护的人少走弯路。

4.4 实现新增、删除和部门统计

新增员工功能需要一个 Modal 弹窗。在组件库中拖入 Modal,在里面放置姓名输入框empNameInput、部门下拉框empDeptSelect、邮箱输入框empEmailInput、状态下拉框empStatusSelect和保存按钮saveEmployeeBtn。把打开弹窗按钮的事件设置为 Open Modal。

然后创建保存员工查询insertEmployee,SQL 内容如下:

INSERT INTO employees (name, department, email, status, created_at) VALUES ( '{{empNameInput.value}}', '{{empDeptSelect.value}}', '{{empEmailInput.value}}', '{{empStatusSelect.value}}', NOW() );

这里通过双花括号把弹窗表单组件中的值取出来,注入到 SQL 中。ToolJet 在运行时会把表达式的值替换成组件的当前值。需要说明的是,字符串字段外面要加单引号;如果组件值本身包含危险字符,会产生 SQL 拼接风险,因此生产环境要尽量限制页面编辑权限并完善输入校验。插入成功后,在保存按钮事件上继续配置:运行insertEmployee,然后运行getEmployees刷新表格,最后关闭 Modal。

删除选中员工功能相对直白。创建一个删除查询deleteEmployee,为了避免用户没有选中任何行时产生误删整表风险,SQL 中特意加了|| -1兜底:

DELETE FROM employees WHERE id = {{employeeTable.selectedRow.id || -1}};

如果当前表格没有选中行,selectedRow.id会是空值,表达式整体会变成-1,删除操作影响 0 行,不会清空整表。然后把删除按钮的事件配置为运行deleteEmployee,成功后再次运行getEmployees刷新表格。页面中还应该给删除按钮设置一定的防误触体验,比如事件链中先弹确认提示,或者依赖 ToolJet 的确认能力。

部门统计功能使用图表组件完成。先创建统计查询departmentStat

SELECT department, COUNT(*) AS cnt FROM employees GROUP BY department ORDER BY cnt DESC;

运行后返回每个部门的员工数量。接着往页面拖入一个 Chart 组件,并把它绑定到{{queries.departmentStat.data}}。ToolJet 的图表配置项和组件版本有关,你可以在 Chart 组件的 Data 字段中选择该查询,并指定 X 轴为department,Y 轴为cnt。预览时就能看到柱状图或饼图。

4.5 运行验证与结果说明

到这里,一个简单的员工管理面板已经成型。整个应用验证流程建议按下面的步骤走一遍:第一步,确认getEmployees查询能手动跑通并返回 5 条数据;第二步,进入预览模式,检查 Table 是否正确显示员工列表,部门统计图表是否出现;第三步,在搜索框输入“研发”或“数据”,确认表格按部门过滤成功;第四步,点击打开新增弹窗,填写姓名、部门和邮箱,点击保存,确认表格新增记录并关闭弹窗;第五步,在表格中选中一条记录,点击删除按钮,确认该记录消失。

如果上述步骤全部通过,就可以点击发布按钮,把应用发布给团队成员使用了。发布后的页面是独立 URL,成员根据分配的账号角色访问,没有账号的用户无法直接打开。ToolJet 在内部工具场景中通常不会把页面匿名公开,而是通过平台的账号权限来管理入口。

5. ToolJet 常见报错与排查思路

5.1 高频问题对照表

不管是自托管部署阶段还是页面配置阶段,ToolJet 都会出现一些比较典型的问题。我把高频问题整理成下表,你在报错时可以先行对照。

问题现象常见原因解决思路
部署后页面无法访问端口被占用或防火墙未放行检查 docker compose 端口映射和系统防火墙策略
初次初始化数据库失败PostgreSQL 密码不对或网络不通查看日志,确认数据库连接参数和依赖服务状态
运行查询提示连接失败业务数据源地址或账号不可达在数据源面板重新填写地址,执行 Test Connection
SQL 查询执行报错SQL 语法或变量拼接格式错误先去掉双花括号表达式,测试纯 SQL 是否可运行
Table 没有数据查询返回的数据不是数组运行查询查看返回数据结构,确认绑定字段是否正确
页面操作按钮无响应事件处理器未配置或配置错误检查目标按钮的 Events 设置,确认是否选择了 Run Query
删除或更新
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/4 23:55:41

MusicFree 歌词源指南:歌词缺失和时间轴漂移怎么处理

MusicFree 歌词源指南&#xff1a;歌词缺失和时间轴漂移怎么处理 【免费下载链接】MusicFree 插件化、定制化、无广告的免费音乐播放器 项目地址: https://gitcode.com/GitHub_Trending/mu/MusicFree 如果你在用 MusicFree 时遇到过歌词源加载不出来、或者歌词和旋律对不…

作者头像 李华
网站建设 2026/9/4 23:55:36

LazyVim 安装教程:5 分钟用 Neovim 懒人配置搭好开发环境

LazyVim 安装教程&#xff1a;5 分钟用 Neovim 懒人配置搭好开发环境 【免费下载链接】LazyVim Neovim config for the lazy 项目地址: https://gitcode.com/GitHub_Trending/la/LazyVim Neovim 原生状态强大但配置繁琐&#xff0c;从零搭建补全、语法高亮、LSP 往往要花…

作者头像 李华
网站建设 2026/9/4 23:53:09

基于MATLAB/Simulink的光伏电池建模与MPPT算法仿真实战

简介&#xff1a;本资源是一套面向新能源领域高校师生、光伏系统工程师及MATLAB/Simulink初学者的光伏建模与控制仿真实践方案&#xff0c;聚焦光伏电池阵列精确建模与最大功率点跟踪&#xff08;MPPT&#xff09;算法验证&#xff0c;解决实际工程中光照、温度变化下功率输出不…

作者头像 李华
网站建设 2026/9/4 23:52:30

运动跟踪评估基准:为什么不能只看MPJPE?

在 motion tracking 的论文和工程项目里&#xff0c;HumanTracker 这个方向很容易被误解为“再做一个更精确的模型”。但名字里真正重要的其实是后半段&#xff1a;Benchmark。模型精度可以靠数据堆出来&#xff0c;评估口径如果混乱&#xff0c;堆多少数据都说不清效果。Human…

作者头像 李华
网站建设 2026/9/4 23:50:49

基于due框架的分布式麻将游戏服务器架构设计与实战解析

简介&#xff1a;本资源是一个基于due分布式游戏服务器框架实现的麻将游戏服务端项目&#xff0c;面向Go语言中级开发者及分布式系统学习者&#xff0c;解决高并发实时对战类游戏后端架构设计与落地难题。压缩包共63个文件&#xff0c;含41个Go源码&#xff08;覆盖网络通信、游…

作者头像 李华
网站建设 2026/9/4 23:50:22

法律AI助手工程实践:用RAG构建可解释的法律问答系统

一起劳动争议案件的当事人&#xff0c;最需要的往往不是“AI 已经给你判了”的结论&#xff0c;而是先有人告诉他&#xff1a;关于这件事&#xff0c;法律是怎么规定的&#xff0c;可以主张哪些权利&#xff0c;举证要准备什么材料。过去这件事只能依靠律师或法律援助机构&…

作者头像 李华