Files
workspace/code/g3soft-erp
2026-10-13 17:29:55 +08:00
..
u
2026-10-13 17:29:55 +08:00
u
2026-10-13 17:29:55 +08:00
u
2026-10-13 17:29:55 +08:00
u
2026-10-13 17:29:55 +08:00
u
2026-10-12 22:25:41 +08:00
u
2026-10-13 17:29:55 +08:00
u
2026-10-09 22:05:02 +08:00
u
2026-10-09 22:05:02 +08:00
u
2026-10-13 17:29:55 +08:00

g3soft-erp

G3Soft ERP 前后端同仓。业务域:海运 / 空运 / 箱管 / 财务 / CRM。

当前状态:前端骨架已搭好并可运行;后端已从原型 fms-api 迁入元数据驱动引擎实现(见 server/README.md)。 元数据驱动引擎(通用查询 / 保存 / 权限)尚未按业务域重构,属后续独立立项。

目录结构

g3soft-erp/
├── pnpm-workspace.yaml      # 仓库唯一配置文件:overrides + allowBuilds
├── web/                     # 前端应用(前端唯一的 package.json 在这里)
│   ├── package.json
│   ├── vite.config.ts
│   ├── vitest.config.ts
│   ├── tsconfig.json
│   ├── .oxlintrc.json
│   ├── .oxfmtrc.json
│   └── src/
├── server/                  # 后端(Maven + Spring Boot,已迁入原型实现)
├── docs/                    # 设计文档
└── README.md

根目录刻意不放 package.json —— 前端可交付物只有 web/ 一个包,那个 package.json 就是 web/package.json。根目录只有 pnpm-workspace.yaml 一个配置文件。

环境要求

  • Node.js >= 20.19
  • pnpm 11
  • g3soft-libs 需与 g3soft-erp 平级(同在 D:\workspace\code\ 下),因为 overrides 用相对路径 link 组件库

快速开始

# 1) 先构建组件库(@g3soft/ui 的 exports 指向 dist,必须先有产物)
cd ../g3soft-libs && pnpm --filter @g3soft/tokens build && pnpm --filter @g3soft/ui build

# 2) 回到本项目
cd ../g3soft-erp/web
pnpm install
pnpm dev          # http://localhost:5090

命令都在 web/ 下跑,根目录没有 package.json,所以根目录敲不了 pnpm dev。

脚本(在 web/ 下执行)

命令 说明
pnpm dev 开发服务器(端口 5090,/api 代理到 8088)
pnpm build 类型检查 + 生产构建
pnpm typecheck 仅 vue-tsc --noEmit
pnpm test Vitest
pnpm lint / pnpm fmt oxlint / oxfmt
pnpm check lint + fmt:check + build(提交前跑这个)

@g3soft/ui 接入方式

组件库的 exports 指向 dist/,所以改完组件库必须重新 build。

开发期通过 pnpm-workspace.yaml 的 overrides 指向本地包:

overrides:
  '@g3soft/tokens': link:../g3soft-libs/packages/tokens
  '@g3soft/ui': link:../g3soft-libs/packages/ui

三个注意点:

  1. overrides 只在 workspace 根生效,写在 web/package.json 里无效。
  2. vite.config.ts 必须保留 dedupe: ['vue', ...]。link 进来的包会带自己的 Vue 副本,不去重会导致组件内响应式失效(组件内部 ref 变化不触发外部渲染)——link 方案最经典的坑。
  3. CI / 其他机器:相对路径依赖目录层级。私库就绪后应把开发期 link: 换成私库版本号。

本地联调组件库:构建时必须先停掉 dev server

上面那条「改完组件库必须重新 build」还差半句:构建组件库时要先停掉本项目的 dev server。

原因是 Vite 监视着 link 进来的 packages/ui/dist/,而 vite build 会先清空再逐个写回产物文件,于是:

  1. 每个产物文件被重写都触发一次 page reload,浏览器反复刷新;
  2. 构建中途 dist/style.css 会短暂不存在,而 src/styles/index.scss 里有 @use '@g3soft/ui/style.css';,Sass 解析时文件已经没了 —— dev server 进程直接崩溃:
[vite] Internal server error: [sass] ENOENT: no such file or directory,
  open 'D:\workspace\code\g3soft-libs\packages\ui\dist\style.css'
  ╷
9 │ @use '@g3soft/ui/style.css';
  │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  ╵
  src\styles\index.scss 9:1  root stylesheet

随后是 ELIFECYCLE Command failed with exit code 4294967295.

  1. 还有一种更隐蔽的:server 没崩,但缓存到了写入中途的模块图,页面白屏、控制台报 Failed to resolve import "./tooltip/Tooltip.js" from ".../dist/index.js"。此时磁盘上的 dist 其实是完整的,问题纯粹在 Vite 缓存。

正确顺序:

# 1) 停掉本项目 dev server(占用 5090 端口)
# 2) 构建组件库
cd ../g3soft-libs && pnpm --filter @g3soft/ui build
# 3) 重新启动
cd ../g3soft-erp/web && pnpm dev

若怀疑是缓存问题(白屏、找不到模块),在启动前额外删掉 web/node_modules/.vite 再 pnpm dev。改 @g3soft/tokens 同理(pnpm --filter @g3soft/tokens build),也要在 dev server 停掉时做。

想要组件库热更新?

link: 指向已构建的 dist/,改源码不会即时生效。若要像 g3soft-libs/docs 那样直连源码,在 vite.config.ts 里加 alias:

resolve: {
  alias: {
    '@g3soft/ui': fileURLToPath(new URL('../../g3soft-libs/packages/ui/src/index.ts', import.meta.url)),
  },
}

环境变量

变量 默认值 说明
VITE_PROXY_TARGET http://127.0.0.1:8088 开发环境 /api 代理目标
VITE_API_BASE /api 接口基础路径
VITE_APP_TITLE G3Soft ERP 应用标题

将来加 H5 端

@g3soft/ui 只给 web 用,H5 不用。 所以两端是基本独立的应用,只是碰巧同仓,不需要抽任何共享层。

加 H5 时的步骤:

  1. 建 h5/ 目录(与 web/ 平级),它有自己的 package.json
  2. pnpm-workspace.yaml 的 packages 改为 ['web', 'h5']
  3. 若 H5 也要用某个 g3soft 包,在 overrides 里加一条;不用就不用加
  4. 各端独立构建、独立部署

仓库纪律(重要)

前后端同仓,但必须各自独立:

  1. 独立构建 —— 前端 pnpm build 不管后端,后端 mvn package 不管前端,任何一方都不触发另一方构建(不要引入 frontend-maven-plugin 这类东西)。
  2. 独立版本 —— tag 分开打(web-v1.2.0 / api-v1.2.0)。
  3. 唯一契约是 HTTP 接口 —— 前端不读后端源码,后端不管前端怎么调;契约写进 docs/。

破坏这三条,同仓的好处立刻变成耦合的代价。

相关仓库

  • g3soft-libs —— @g3soft/ui(组件库)、@g3soft/tokens(设计变量)。web 端 UI 一律用组件库,不另起一套。