开源ERP ever-gauzy全解析:从部署到二次开发实战指南
2026/9/16 9:50:26 网站建设 项目流程

如果你正在评估开源 ERP 或一体化管理平台,大概率会在搜索过程中撞见ever-gauzy这个仓库。我第一次看到它时,第一反应是“这名字真怪”,但点进去之后发现,这几乎是目前 Node.js 生态里最完整的企业管理系统之一。它不是一个简单的进销存工具,而是把预算、人力、客户、项目、工时、发票这些业务模块全部整合到了一起。这篇文章我会从实际部署到二次开发,完整拆解我使用 ever-gauzy 的整个过程,包括环境配置、踩坑记录、源码结构分析,以及如何在此基础上扩展自己的业务模块。如果你正准备选型开源企业管理软件,或者想在现有 ERP 上做定制,这篇内容应该能帮你少走很多弯路。

1. ever-gauzy 到底是什么?先把它和常见 ERP 的区别说清楚

1.1 它不是一个简单的进销存

很多人一看到 ERP 就以为是进销存加财务,ever-gauzy 的边界远不止这些。从功能模块看,它覆盖了销售管道、客户关系管理、员工花名册、考勤工时、项目任务、费用报销、合同发票、采购库存、会计科目等十几条业务线。更关键的是,这些模块不是孤立存在的,而是在同一套组织架构下互相联动。比如一个销售订单成交后,系统会自动生成应收发票,同时关联到对应项目和负责员工的工时记录,财务人员可以直接在会计模块看到这笔收入对账。这种端到端的流程闭环,是很多开源 ERP 做不到的。

1.2 一张表看懂它的模块边界

为了让你快速判断它适不适合自己,我把它的核心模块按业务域做了个梳理:

业务域主要功能典型使用场景
销售与 CRM交易管道、客户管理、跟进记录销售团队维护潜在客户,跟踪商机阶段
项目与任务项目计划、任务看板、里程碑项目经理拆解任务并分派给团队成员
人事与工时员工档案、考勤、工时表、休假申请HR 统计考勤,员工提交工时
财务与发票发票、账单、费用报销、会计科目财务按月生成客户账单和内部报销
库存与采购产品、仓库、采购订单供应链团队管理库存和采购计划
行政与客户门户知识库、客户自助登录查看订单客户进入门户查看项目进度和发票

这些模块并非全部开箱即用,有些需要额外配置,但整体覆盖面在开源领域已经非常难得。

1.3 技术栈视角:为什么 Node.js 团队看到它会更亲切

传统开源 ERP 大多是 PHP 或 Python 技术栈,比如 Odoo 和 ERPNext,它们的功能确实强大,但如果你是 Node.js 技术团队,定制和扩展起来会有明显的知识迁移成本。ever-gauzy 的后端基于 NestJS 和 TypeORM,前端使用 Angular,整个仓库是 monorepo 结构。也就是说,从数据库实体到 REST API,再到 Angular 服务层,全部是 TypeScript 一脉相承。业务团队可以只维护一套语言体系,不需要同时养 PHP、Python 和多套前端语言,这一点对我这种长期在 Node 生态里开发的人来说非常讨喜。

2. 本地跑通的全过程:依赖、数据库、seed 数据

2.1 环境准备环节最容易翻车的三点

我是在一台全新的 Ubuntu 22.04 服务器上做部署测试的,踩坑要素基本都集中在三点:Node 版本、PostgreSQL 版本、Yarn 版本。ever-gauzy 官方对 Node 版本有明确要求,我用的是 Node 18 LTS,运行得比较稳。如果你本机装了 Node 20 或更高,也可能会遇到一些原生模块编译不兼容的问题。PostgreSQL 建议直接用 14 或 15,版本太老会导致 TypeORM 连接驱动报错。另外,这套仓库是典型的 Lerna + Yarn workspace 结构,如果只用 npm 安装依赖,大概率会在依赖软链和 hoisting 阶段出问题,所以强烈建议统一用 Yarn 1.x 经典版。

2.2 安装依赖时的取舍

我的第一步是克隆仓库,然后复制.env.example.env,接着执行yarn install。这一步耗时相当长,慢的时候可能需要十几分钟,因为要拉取 API、UI 以及桌面端 Electron 相关的全部依赖。如果网络状况不理想,建议设置 yarn 的镜像源。安装过程中如果看到node-sass或者sharp的编译错误,先别慌,通常是本机缺少构建工具,执行一遍sudo apt install build-essential libpng-dev之后重新安装就好。

依赖装好后,我习惯先跑一次yarn build,把前后端的编译结果都生成一遍,这样后面seedstart:server的时候会快很多。如果你跳过这步直接启动,开发服务器仍然会实时编译,但首次启动会比较卡,尤其 Angular 项目的 dev server 首次编译可能需要几分钟内存。

2.3 数据库初始化与 seed 操作

ever-gauzy 默认使用 PostgreSQL,需要在.env里填好数据库连接信息。不同版本的环境变量命名会有一点差异,但核心字段基本就是DB_NAMEDB_USERDB_PASSDB_HOST。我先在 PostgreSQL 里创建了一个名为gauzy的数据库,然后执行了yarn seed。这个 seed 命令会自动跑数据结构迁移,并写入一套演示组织、员工和系统内置枚举数据,对本地预览很有帮助。

如果你不想要演示数据,只希望建立空库,可以直接跑迁移命令而不是完整 seed。我实际测试下来,seed 过程大概会持续几分钟,期间日志会滚动输出很多 NestJS 的模块初始化信息,不用盯着它,泡杯茶等它结束就行。seed 完成后,再分别启动 API 和 UI 服务,浏览器打开localhost:4200,就能看到登录页。使用 seed 生成的默认管理员账号登录,系统会引导进入工作台。

2.4 启动后第一件事:登录与控制台

登录进系统后,我建议先不要急着点各个菜单,而是进入设置页面看一下“租户和用户”的配置。ever-gauzy 的权限模型跟大部分单体系统不一样,它先有租户(Tenant),租户下再建立组织(Organization),用户必须在特定组织下才具备业务数据权限。第一次登录时你会看到一个默认组织,这里面包含了销售管道、员工列表等 demo 数据。如果在左侧菜单发现某些模块没有数据,不是 bug,而是因为你当前用户没有分配到对应组织的角色权限。

3. 我踩过的坑:从连不上数据库到界面白屏的排查链路

3.1 数据库连接报错:问题往往不在密码本身

部署过程中见过的最高频报错,是 API 启动时提示Unable to connect to the database。大多数人会先去检查密码,但我的排查结果显示,真正的原因通常是.env和数据库实际配置不一致,尤其是DB_TYPE或端口被写错。另外,如果你在 Windows 上跑 PostgreSQL,默认安装经常不会启动服务,需要去服务管理器里把postgresql-x64-14服务启动起来。还有一个隐藏很深的点:ever-gauzy 支持通过环境变量区分 API 数据库和桌面数据库,如果只配了 API 库,Electron 桌面端启动时还是会报连接失败。我后来直接把桌面端相关配置统一指向同一个 PostgreSQL 实例,才彻底消停。

3.2 编译过程中 Node 内存溢出

前端 Angular 和整个 monorepo 同时编译时,很容易遇到JavaScript heap out of memory。这个问题在我机器上出现过好多次,原因是默认 Node 堆内存不够。解决方式是在启动命令前加上NODE_OPTIONS=--max_old_space_size=4096,或者在 package.json 的启动脚本里注入这个参数。如果你用的版本比较老,可能还需要显式调整 Angular 的budget配置,否则代码量一大就会出现警告甚至中断编译。这一条对任何大型 monorepo 项目都适用,建议直接写进你的开发文档里。

3.3 seed 出现重复数据的根因

yarn seed跑了几次之后,我发现页面上组织列表出现了重复的演示组织,后来定位到是因为我中途手动中断过 seed,导致部分幂等逻辑没有执行完整。再跑 seed 时,系统不会自动清理之前已经插入的部分数据,于是出现了重复。解决办法也很简单:先清空数据库再重新 seed,或者直接重建一个库。这个坑提醒我,在操作开源 ERP 时,不要想当然认为 seed 是可以反复安全执行的,最好每次都在干净库上操作。

3.4 前端 404 / 白屏:路由回退与静态资源路径

另一个让我卡到快崩溃的问题,是 API 启动正常但前端打开后一直是白屏。浏览器控制台的报错涉及一些静态资源 404,同时还伴随 Angular 路由回退问题。排查后发现是因为我直接用localhost:4200访问没问题,但一旦通过 Nginx 反代到子路径,Angular 的base href没有跟着改,所有 JS/CSS 请求都指向了根路径。后来我把 Nginx 配置里的location做了精确匹配,并在 index.html 里设置好base href="/",白屏问题就消失了。

4. 核心模块拆解:一个成熟开源 ERP 的设计思路

4.1 租户与组织的分层权限模型

ever-gauzy 的权限模型几乎可以作为 SaaS 后端设计的教科书案例。最上层是租户,租户是一个独立数据域,下面是组织,组织之间业务数据彼此隔离。用户在同一个租户下可以同时属于多个组织,但每个组织里的角色权限不同。这种设计在真实企业场景里非常有用:集团下多个子公司各自独立管理,但集团总部可以跨组织查看汇总数据。API 层通过 JWT 中的租户信息解析当前上下文,后端 service 里大量使用了tenantIdorganizationId的双重过滤条件。这提醒我们,如果要做自己的多租户系统,租户隔离必须在数据库查询层统一约束,而不是在每个业务接口里各自处理。

4.2 基于 TypeORM 的实体关系设计

看代码的时候,我特别关注了实体关系定义。ever-gauzy 的实体类分散在各自模块中,通过装饰器声明关系,比如用户和员工是一对一,员工和部门是多对一,订单和发票是一对多。TypeORM 的RelationIdJoinColumn用法很规范,几乎可以作为企业级 TypeScript 项目的代码规范参考。值得注意的一点是,它的每张业务表和数据库迁移文件都是独立维护的,修改实体后需要手动生成 migration,而不是在运行时自动同步表结构。这会增加一点开发心智负担,但好处是生产环境可以用迁移脚本来做版本化变更,避免数据表结构混乱。

4.3 消息队列与实时通知的落地方式

在本地开发时你可能察觉不到,但 ever-gauzy 设计了不少异步任务,比如邮件发送、定时生成任务提醒、报表异步导出。这些场景依赖消息队列来解耦,后台框架使用了 NestJS 的bull模块接 Redis。我们做二次开发时,如果某个操作特别耗时,也应该借鉴这种模式:先写一个异步 processor,再通过队列在 controller 里触发,避免用户请求一直卡住。实际部署时,一定要记得把 Redis 服务纳入到运维清单里,否则队列任务会不断重试但不会真正执行。

4.4 可配置仪表盘的实现思路

它的工作台首页不是写死的,而是由多个可视化组件动态拼装。每个组件对应一个后端聚合接口,比如“本月销售额”“待处理订单数”“员工请假趋势”。这些聚合接口基本都是通过 service 层跑复杂查询,再组合成统一的数据结构。整体下来,我发现它的数据呈现思路很清晰:后端只提供结构化的汇总数据,前端负责布局和图表渲染。如果你想自定义首页指标,不必大改前端页面,只需要新增一个类似的数据聚合服务,再挂到一个组件上就能快速上线。

5. 二次开发手册:从改数字段到新增业务模块

5.1 最小改动:调整页面字段显示

对绝大多数企业来说,二次开发第一步都是改字段,比如把“客户名称”改成“客户全称”,或者在员工表单里加一个“工号”字段。这里我推荐一个低风险的路径:直接在 Angular 表单组件里调整显示标签,后端实体暂时不动。这样不会影响数据库结构,改完刷新页面就能生效。等确认字段确实需要持久化,再去 entity 里增加@Column属性,并生成新 migration。我的经验是,先改前端解决业务临时需求,再集中做数据库结构调整,比一上来就大动干戈要稳妥得多。

5.2 新增一个业务模块的标准姿势

如果是新增一个完整业务对象,比如“资产登记”,我通常会在apps/gauzy-api/src下建立一个资产模块,包含AssetModuleAssetControllerAssetServiceAssetEntity四个文件,并仿照已有模块的命名风格编写。Controller 中基本只做参数校验和调用 service,所有复杂业务逻辑都塞进 service,这样单元测试和维护都会简单很多。前端角色也一样,新增一个 features 目录下的页面模块,在路由配置里指向新组件,再通过菜单权限控制入口。整个过程能跑通的前提是:前后端使用同一套 TypeScript 类型意识,接口返回的结构尽量保持一致。

5.3 扩展 API 时需要留意的权限注解

修改后端接口时,最容易忽略的是权限装饰器。ever-gauzy 的每个可访问接口基本都使用了@Permissions()装饰器,如果你在自定义接口上漏掉权限描述,登录用户即使有页面访问权限也会拿到 403。我在开发一个自定义报表接口时遇到过这个问题,后来发现必须同步在PermissionsEnum枚举里增加一个CUSTOM_REPORT_VIEW权限,并给角色分配后才生效。另外,接口层的 Query 参数里经常会用到TenantBase相关 DTO,新增查询条件时要注意类型继承,不然请求参数不会被正确解析。

5.4 自定义数据源:在既有表结构上做接缝扩展

很多开源 ERP 的扩展点都在数据库层面。如果你想接入企业已有的系统,比如从旧的 CRM 里同步客户,比较合理的做法不是去改核心表,而是创建一个集成表,保留旧系统的主键和同步时间戳,再通过后台定时任务把数据映射到 ever-gauzy 的业务表里。这种方法不会在升级版本时和官方实体产生冲突,也可以随时回滚。我在实际项目中就用这种方式接入了企业微信通讯录,角色同步也只做新增和更新,不做物理删除,保证误操作后还能恢复数据。

6. 生产部署与运维建议

6.1 Docker Compose 方式的好处

如果只是本地开发,直接跑源码服务问题不大,但生产环境我更推荐 Docker Compose。ever-gauzy 官方提供了 compose 文件,里面包含了 API、UI、PostgreSQL、Redis 等服务。容器化的好处是能够把 Node 版本、数据库版本、系统依赖全部锁定在同一套环境里,避免“在我机器上明明能跑”的尴尬。我自己的服务器配置是 4 核 8G,跑一套 compose 之后 CPU 和内存都比较宽裕。如果你团队有 Docker 基础,这会是最省心的部署路径。

6.2 Nginx 反代与 HTTPS

生产环境的 UI 往往不是直接暴露 80 端口,我会用 Nginx 做反向代理。核心配置是:location /api转发到 API 服务端口,location /转发到 UI 服务端口,同时启用 WebSocket 代理,否则系统里的实时通知和在线状态功能会失效。SSL 证书方面,我使用 Let’s Encrypt 自动续期,没有做特殊配置,但要注意 Nginx 里需要正确设置proxy_set_header HostX-Forwarded-Proto,这样系统生成链接时才不会出现 http/https 混用的问题。

6.3 数据库备份与迁移

数据库是整个系统最核心的资产,我在自动化运维脚本里每天执行pg_dump备份,备份文件保留最近 7 天,并同步到独立的对象存储。除了常规备份,建议在每次升级前手动导出一份 SQL,因为 seed 或 migration 脚本在升级时可能会改写表结构,出错时至少能恢复原状。升级完毕后,最少要做一轮“创建订单到生成发票再导出报表”的冒烟测试,确保核心链路没有断裂。

6.4 版本升级需要注意的事项

ever-gauzy 迭代速度不算慢,升级时要特别关注两个文件:CHANGELOG.mdmigration文件夹。正式升级前,我会先看发布说明里是否有破坏性变更,比如环境变量重命名、数据库表字段修改、API 路由路径调整。然后再在测试环境完整执行一次升级流程,等稳定之后再操作生产环境。如果在升级过程中出现自定义模块的依赖包版本冲突,先不要盲目改源码,优先检查是不是没有同步官方仓库的依赖升级,很多时候yarn install一次就能解决。

7. 我的真实使用体会

从部署 ever-gauzy 到基于它做业务定制,我最大的感受是:开源 ERP 并不等于“省心”,但如果你愿意花时间摸清楚它的设计套路,它能省下从零搭建一套企业级后台的大量时间。它的多租户模型和模块拆分方式都很成熟,二次开发成本远低于我从前的预期。最让我意外的其实是它的工时和项目管理模块,和财务发票链路打通之后,整个团队的项目核算都变得清晰了。如果你有长期使用的打算,建议从本地 seed 环境开始,先用 demo 数据把每个菜单点一遍,再决定从哪个业务模块切入改造。毕竟,选型这件事,实际点了页面才知道合不合适。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询