上个月有个做跨境电商的朋友找我,说公司二十几个人了,财务还在用 Excel 和微信群对账,采购、销售、报销全散在钉钉、飞书和线下单据里。他问我:有没有一套能自己部署、数据不出公司、最好不用每年交会员费的管理软件?我二话没说,把 ever-gauzy 的链接丢了过去。他看完 demo 之后当场决定在测试环境试跑,后来我们花了一个周末,就把进销存、发票、考勤的全流程跑通了。
很多人听到 ever-gauzy 这个名字会觉得陌生,甚至觉得它名字拗口不好念。但只要你在 GitHub 上按星标排一下"开源企业管理平台",它基本都排在前面。官方仓库名就叫 ever-gauzy,是由 Ever 团队维护的一体化业务管理平台,技术栈清一色 TypeScript:后端是 NestJS,前端是 Angular,桌面端用 Electron 再套一层,数据库默认 PostgreSQL,也支持 SQLite、MySQL 这类关系型数据库。它不是某个单一功能的开源工具,而是把 CRM、销售、采购、库存、发票、会计、HR、考勤、工资、项目、任务、时间追踪、BI 报表全部塞进了一个项目里。
这篇内容不适合只想看介绍的人。我会从"它到底解决了什么问题"讲起,把部署链路、二次开发方式、选型对比,以及上线后真正会遇到的高频问题全部过一遍。如果你正好在帮公司或客户选一套开源业务系统,或者你本身就是做 Node.js/前端开发、想找一个可以租住研究的完整全栈项目,这篇会给你省下很多趟坑的时间。
1. 先弄清 ever-gauzy 到底装下了多少管理模块
1.1 从名字说起:为什么它值得单独开一篇
ever-gauzy 并不是一个新产品。它的前身叫 Gauzy,很多老用户现在还在用旧名字搜索。后来 Ever 团队把产品线整体升级,仓库名改成了 ever-gauzy,目的其实是要建立一个不只是记账、不只是卖货的全流程运营底座。官方定位是"现代开源企业管理平台",覆盖范围比大多数国内团队理解的传统进销存系统要广得多。
我刚开始接触的时候,也很怀疑一个开源项目能不能把财务、人事、业务拉通。真去翻源码才发现,它是认真的。项目里按业务域划分出了客户关系、采购、发票、库存、会计总账、人力资源、项目、报表等多个独立目录,每个目录下都有完整的实体定义、服务、控制器和前端页面。这种结构意味着它不是演示性质的玩具,而是可以按模块拆开部署、按业务裁剪的真实系统。
1.2 拆开看:五大核心模块是怎么闭环的
我只花半天看完它的模块清单,就明白了它的价值。第一块是 CRM 客户管理,线索、联系人、沟通记录、跟单状态都有;第二块是销售和采购流程,从报价、订单、合同、发货到销售发票;第三块是库存与产品管理,SKU、仓库、条形码、多仓库盘点都支持;第四块是财务与会计,复式记账、总账、应收应付、现金流量表、利润表;第五块是人力资源,员工档案、排班、考勤、请假审批、工资单,还带项目打卡和工时统计。
关键不是这些模块单独存在,而是它们数据打通。举个例子:你在 CRM 里把一个线索转成客户,从报价单生成销售订单,订单发货后又自动生成应收发票,发票确认收款后写进会计总账。等到月底,系统直接可以拉出按客户、按产品分类的利润报表。整个过程在 ever-gauzy 里是一条闭环,不需要像传统方案那样在 CRM 导一遍数据、在财务系统再导一遍。
1.3 技术底座:Angular、NestJS 与 PostgreSQL 组成的全家桶
这套技术栈对我这种前端背景的人非常友好。后端把 NestJS 的模块化能力用得很彻底,每个业务域就是一个 NestJS Module,想加功能就是在模块边界内加 Controller 和 Service。前端是 Angular 的企业级写法,状态管理、路由守卫、懒加载、权限指令都是现成的,不是那种拿 jQuery 拼出来的后台模板。数据库层用了 TypeORM,实体定义和关系映射都在 TypeScript 里写,换数据库时不需要改业务代码。
再加上 Electron 桌面端,它能把整套管理系统打包成 Windows、macOS、Linux 的本地应用。也就是说,不只是团队成员在浏览器里用,老板自己装个桌面客户端也能看报表。这种"一套业务逻辑、三种运行形态"的架构,在开源管理软件里并不多见。
2. 部署这台“业务全家桶”:完整链路与三个最容易翻车的细节
2.1 环境准备:不是装个 Node 就行
我把仓库拉下来之前,先看了一遍官方 README 的 prerequisites。硬性环境就三样:Node.js、Yarn、PostgreSQL。Redis 在很多功能里会被用到,尤其是定时任务和消息队列,我建议提前装好。如果是纯体验,官方也支持 SQLite,但我不建议正式环境用,因为多模块并发写的时候,SQLite 的锁机制容易拖后腿。
Node.js 版本是第一个容易出问题的地方。ever-gauzy 对 Node 版本有最低要求,我记得至少是 Node 18 以上的 LTS。如果你机器上同时装了多个 Node 版本,建议用 nvm 切换到这个项目需要的版本。安装依赖也别用 npm,官方是围绕 Yarn workspace 组织的,用 npm 装会出现依赖 hoisting 不一致的问题,后面跑构建时各种怪错误。
数据库那一层,我直接拉了官方 Docker 镜像起 PostgreSQL,这样不会污染本机环境。建库的时候注意统一编码,默认 UTF8 就好,不然后面存客户名字的多语言字符会乱。启动 PostgreSQL 之后,在项目根目录把 .env.example 复制成 .env,重点检查数据库连接四件套:host、port、username、password。
DB_HOST=localhost DB_PORT=5432 DB_NAME=ever_gauzy DB_USER=postgres DB_PASS=postgres这个小文件是整个系统的总开关,不只是数据库,后面邮件服务、对象存储、Redis、JWT 密钥全在这里配置。
2.2 从拉代码到看见登录页:一套我能复现的命令
环境准备好之后,整个安装过程基本就是一条直线。把仓库克隆下来,安装依赖,构建,灌种子数据,然后分别起后端和前端。
git clone https://github.com/ever-co/ever-gauzy.git cd ever-gauzy cp .env.example .env yarn install yarn build yarn seed yarn start:api yarn start:gauzy这里我重点说两个命令。yarn build会把所有 workspace 包和前后端应用全部编译一遍,第一次跑耗时很长,中途不要打断,不然 node_modules 里的缓存状态会非常混乱。yarn seed是灌初始化数据,它会创建超级管理员账号,顺便生成一套用于演示的客户、商品、订单、发票数据。没有这套种子数据,你登录进去面对的是空白系统,很难判断功能到底好不好用。
启动之后,后端 API 默认跑在 3000 端口,前端 Angular 开发服务器跑在 4200 端口。浏览器打开http://localhost:4200,用种子脚本创建的管理员账号登录,就能进主页。整个过程在我这里用了不到二十分钟,大部分时间都花在依赖安装和 TypeScript 编译上。
2.3 部署时我实际踩过的三个坑
第一个坑是 Node 版本带的 OpenSSL 兼容问题。如果你用旧版 Node 跑新版本依赖,构建时经常报ERR_OSSL_EVP_UNSUPPORTED,网上有人让你加NODE_OPTIONS=--openssl-legacy-provider,我试过,这是一把双刃剑,加了之后可能压掉一个错误,又冒出来另一个。正确做法是直接把 Node 升到项目要求的 LTS 版本,别在这个上面省事。
第二个坑是端口和跨域。默认情况下,前端在 4200,后端在 3000,两者是不同源。如果 API 地址没配对,登录页根本发不出请求,浏览器控制台永远只是 CORS 报错。你需要检查的是.env里的 API 地址,再确认后端的 CORS 白名单里有没有把前端地址放进去。很多人在数据库上折腾半天,结果只是前端把 API 地址写错了。
第三个坑是时区。系统很多时间字段默认按 UTC 存储和展示,如果你直接拿国内服务器跑,报表里会发现订单日期和考勤打卡时间差了八小时。我当时的解决办法是在.env里把应用时区显式设成Asia/Shanghai,数据库实例也保持一致,并且让所有前端展示时统一走应用的时区配置,别依赖浏览器本地时区。这个坑一开始不明显,等月底对账的时候才暴露出来,让人一度怀疑财务模块算错了账。
3. 二次开发:用三十行代码扩一个审批模块的完整过程
3.1 新模块从哪下手:顺着 NestJS 的模块边界走
选它做二次开发的人,多半是看中了它的模块化。我自己给一家企业加了内部费用审批流,整个过程没有改动原有业务代码,只是顺着它的模块边界新增了一个功能模块。后端加模块就是新建一个 NestJS 的 feature 目录,里面放 Entity、Controller、Service、Module 四个文件,然后在根模块里注册。
我先定义了一个审批请求的实体,字段包括标题、申请原因、状态、申请人、审批人,这样就够用了:
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm'; import { Employee } from '../employee/employee.entity'; @Entity('approval_request') export class ApprovalRequest { @PrimaryGeneratedColumn('uuid') id: string; @Column() title: string; @Column({ type: 'text' }) reason: string; @Column({ default: 'pending' }) status: 'pending' | 'approved' | 'rejected'; @ManyToOne(() => Employee) applicant: Employee; @Column({ nullable: true }) approverId: string; }实体写好之后,写一个基础的 Controller,暴露列表、提交和审批三个接口。把模块在app.module.ts里挂上,TypeORM 会自动同步表结构。整个过程确实是三十行代码的规模,前提是你对 NestJS 的依赖注入和装饰器风格不陌生。它的底层是标准 TypeORM,我不需要额外去学一套私有 ORM,这对业务型项目来说极其重要。
3.2 前端页面懒加载路由与服务调用
后端接口就绪后,前端是另一个战场。ever-gauzy 用 Angular 的路由懒加载,新增页面不需要侵入主布局,只要在路由表里加一条指向新模块的路径。我写的路由大概是这样:
{ path: 'approval', loadChildren: () => import('./approval/approval.module').then(m => m.ApprovalModule) }组件里走 HTTP 客户端调用 API,它已经封装好了统一的请求基地址、鉴权头和错误拦截器。我第一次调用的时候没有复用它的服务基类,自己直接HttpClient请求,结果登录态没有带上,接口一直报 401。后来改成继承它的宿主服务,问题就消失了。这个经验告诉我们:扩展 ever-gauzy 前端时,先翻一下它已有的 ApiService 和拦截器,再决定要不要自己造轮子。
新页面挂上去之后,菜单栏还需要适配。它菜单是后端返回的配置,不是前端写死,这其实是一个很聪明的设计。管理员在界面上配好菜单数据,前端根据权限点渲染。你要让新模块出现在某个角色眼里,就去管理系统权限配置里把对应菜单项和角色绑定起来,不用改代码。
3.3 权限点怎么挂到菜单上:RBAC 的最短路径
ever-gauzy 的权限模型是典型的 RBAC:用户属于角色,角色绑定权限点。权限点在系统里就是一个个字符串标识,后端接口用装饰器做校验,前端用指令控制按钮显示。整个过程比大多数自研后台要规整,难点反而不在技术,而在权限粒度的设计。
不少新手一上来就把审批功能做成"管理员全部能看、员工全部只读",但真实业务里通常还要细分到部门层级。这里我给个建议:第一版先做角色级的粗粒度控制,所有申请人都能提交,财务主管角色可以审批,管理员能看到所有状态。等跑通之后再考虑数据范围的精细隔离。别一上来就设计一套复杂的树状权限,否则开发周期会被拖得很长。系统本身提供了足够的扩展入口,真正的难点在业务梳理,而不是写代码。
4. 选型参考:ever-gauzy 和 Odoo、ERPNext 的差别到底在哪
4.1 三个开源管理系统的横向对比
很多人在选型时会把 ever-gauzy、Odoo 社区版、ERPNext 放一起比较,这三个确实是目前最常被提起的开源管理软件。我自己的判断标准很简单:看技术栈能不能接住你的团队,看模块完整度够不够用,看 License 允不允许你想要的用法。
| 对比项 | ever-gauzy | Odoo 社区版 | ERPNext |
|---|---|---|---|
| 主力技术栈 | TypeScript + Angular + NestJS | Python + PostgreSQL | Python + Frappe + MariaDB |
| 核心模块 | CRM、进销存、财务、HR、项目、报表 | 销售、采购、库存、会计、物流等 | 销售、采购、库存、会计、HR、项目 |
| 二次开发门槛 | 低到中,前端团队可快速上手 | 中高,需要懂 Python 和 XML 视图 | 中,Python 和入门友好的 Frappe 框架 |
| 界面观感 | 现代,可选 Electron 桌面端 | 功能多但界面略显臃肿 | 简洁但视觉风格偏传统 |
| 许可证 | AGPL-3.0 | LGPL-3.0(社区版) | GPL-3.0 |
| 适合团队 | 前端生态出身、想掌控全套代码的技术团队 | 需要成熟生态、愿意走商业服务路线的团队 | 喜欢 Python、中小型组织 |
从这张表能直接看出,ever-gauzy 最大的差异点是它整个技术栈建立在 TypeScript/JavaScript 生态上。如果你的团队主力是前端工程师,又不想被 Python 和 Frappe 框架的学习成本拖住,它几乎是顺手的。反过来,如果你的团队熟悉 Python 并且更看重社区生态的广度,ERPNext 和 Odoo 也很能打。
4.2 什么团队闭眼选,什么团队建议绕道
我自己判断"适不适合用"会看三个条件。第一,团队有没有至少一个熟悉 TypeScript 的人。缺了这个人,部署报错和二次开发都会很难受。第二,业务是否明显跨越多个管理域。如果你只差一个记账工具,用 ever-gauzy 显得沉;如果你同时要做客户、库存、订单、工资,那就有理由上一套全家桶。第三,是否有数据自主可控的要求。它完全自托管,数据能全程留在你自己的服务器和数据库里,这对很多对数据敏感的企业是硬需求。
也有不适合的情况。如果你的公司没有任何技术人员,买完服务器就没人维护,那我更建议用付费托管方案,别自己扛一套全家桶。另外,如果业务流程极其特殊,需要大量如本地化审批流、电子发票对接这类能力,开源系统只能给你底座,剩下要补的定制量可能超出想象。选它不丢人,选它但没做定制量评估,才是后面项目失控的根源。
4.3 AGPL 许可是个绕不开的合规话题
这点必须放在最显眼的位置说。ever-gauzy 使用的是 AGPL-3.0 许可证,和 GPL 相比,它不仅要求你分发软件时开源衍生代码,还特别强调如果你通过网络向用户提供服务,也要把对应的修改后源代码开放给这些用户。简单理解:如果你基于它给客户做了一个私有部署版本,并且这个版本里有你自己的二次开发代码,你把软件交付给客户时,通常要按 AGPL 要求把修改后的源码提供给客户。如果你的业务是把这个系统改一改,作为 SaaS 对外运营,情况会更加敏感,需要和法务评估一下 in-house 使用和对外服务的边界。
我不是法律专业人士,这里不给你下结论,但每家公司在选型时都应该把许可证这一条放在功能评估之前。先搞清楚自己的商用方式能不能承接 AGPL 的义务,再决定要不要在它上面投入开发资源。这一点如果不提前想清楚,项目做了一半再来补协议上的洞,会很被动。
5. 正式跑起来以后:三个月的运维与优化笔记
5.1 报表变慢之后,先查 SQL 而不是加服务器
系统上线第一周很流畅,第二周开始,财务同事反映月末报表加载要转好几秒。我第一反应不是加服务器配置,而是去看数据库里到底执行了什么。ever-gauzy 的报表模块虽然内置了 BI 界面,但底层还是大量多表 JOIN 和统计数据聚合。数据量到了几十万单之后,下面明细查询不稳定很正常。
我的做法是打开 PostgreSQL 的慢查询日志,把执行时间超过一秒的语句抓出来,逐条分析执行计划,看看哪些关联字段缺索引。它很多业务表的createdAt、tenantId、organizationId都是高频过滤条件,但它们不一定都建了联合索引。我给几个关键报表表补上了联合索引,查询时间直接降了一个数量级。对于月度聚合报表,我还建了物化视图,月末跑一次刷新任务,日常打开报表就是查一个已经算好的结果集。这套组合拳下来,报表页基本做到秒开。
5.2 定时任务与异步队列是怎么运转的
ever-gauzy 的任务系统依赖 Redis 和 Bull 队列,邮件发送、定时生成发票、统计数据同步这些重活都会丢进队列异步执行。如果你忘了装 Redis,或者 Redis 地址配置错了,系统不会直接崩,但很多后台任务会一直 pending,表现为邮件发不出去、报表数据不更新、定时任务不触发,排查起来特别迷惑。
我的运维日常里,每个星期会主动看一眼 Bull 的队列监控面板,确认没有积压的死信任务。偶尔 Redis 里的历史任务会堆积,我会在低峰期清掉旧队列缓存。还有一个经验:不要把定时任务领域绑定在应用进程里,跨平台部署时要保证只有一台实例开启 Worker 模式,否则多个实例同时去跑同一个任务,容易产生重复发票或者重复邮件。这在单机部署时不会暴露,一旦上集群就立刻踩雷。
5.3 我常用的三招故障排查
系统跑久了,问题通常集中在这三处。第一招是看后端日志,NestJS 的日志输出格式很规整,启动后再起 API 时,任何路由报错和数据库错误都会直接打到控制台,先从日志尾部往上看,别一上来就翻源码。
第二招是确认三层服务是不是都活着:PostgreSQL 能连、Redis 能 ping 通、API 进程没有被 OOM 杀掉。很多"页面打不开"的假象,最后发现是服务器内存不足,Node 进程被系统杀了,而前端站点本身没挂,所以看起来特别像后端莫名崩溃。我给服务加了一个简单的健康检查接口,每三十秒探一次,出问题比用户发现得早。
第三招是重置数据。如果只是在测试环境体验,数据被玩乱了,别想着手动清理,直接重新跑yarn seed就可以把系统恢复到初始演示状态。这个操作在生产环境别乱用,但在开发测试阶段非常好使,能在五分钟内把环境从"改坏了"拉回"可以继续玩"。
我在实际部署中的体会是,ever-gauzy 最大的优点不是某个单点功能惊艳,而是它把零散的业务模块缝成了一件合身的衣服。缝线不完美,但版型在,你拿着剪刀在正确的位置修修改改,它就能合身。最后再分享一个小技巧:如果你是第一次接触这套系统,不要急着深入源码,先用种子数据把 CRM 跟单、销售订单、库存出入库、工资单四条主流程各走一遍,建立对"数据流向"的整体感觉,之后无论是改配置还是写模块,都会顺手很多。