开发指南 / Development
环境要求
| 工具 | 版本 |
|---|---|
| JDK | 8 |
| Maven | 3.6+(backend/.mvn/maven.config 自动 -s .mvn/settings.xml,走阿里云公共仓,绕过本机 JD Artifactory) |
| Node.js | 16+ |
| Yarn | 1.x |
| MySQL | 8 |
| Redis | 5+ |
启动步骤
本地 MySQL / Redis 只跑在 Colima(Docker),不要再用 brew services 起本机实例(端口会冲突)。
# 0. Colima(首次需盘镜像;国内勿直连 GitHub)
# 加速门户:https://github.akams.cn/ (拼法 https://<node>/https://github.com/...)
# 例:curl -fL -o ~/Downloads/ubuntu-24.04-minimal-cloudimg-arm64-docker.raw.gz \
# 'https://github.dpik.top/https://github.com/abiosoft/colima-core/releases/download/v0.10.4/ubuntu-24.04-minimal-cloudimg-arm64-docker.raw.gz'
colima start --cpu 4 --memory 8 --disk 40 \
--disk-image ~/Downloads/ubuntu-24.04-minimal-cloudimg-arm64-docker.raw.gz
# Docker Hub 国内源:~/.colima/default/colima.yaml → docker.registry-mirrors
# (本机无 compose 插件时用 docker-compose)
# Agent 全局规则:~/.cursor/rules/github-download-proxy.mdc
## 5 分钟 Vision 自迭代(可选)
```bash
./scripts/agent-loop-vision.sh # 默认每 300s 唤醒;PROMPT 每次读 scripts/agent-loop-vision.prompt.md
# AGENT_LOOP_VISION_INTERVAL=600 ./scripts/agent-loop-vision.sh
选题规则在 scripts/agent-loop-vision.prompt.md:常驻指令 = 持续优化 UI/UX,不要停(体验轨偏置;每 tick 必须交付前端可见体验改进)。PM 发现→ROI→验证→commit;禁止默认 idle;改 prompt 即可,不必重启 shell。agent 回报 idle 时也不退出,5m 继续唤醒。
双周发版笔记(用户向):
./scripts/cut-release-notes.sh --dry-run
./scripts/cut-release-notes.sh # → docs/releases/YYYY-MM-DD.md
说明见 docs/releases/README.md。
1. 起数据库
docker-compose up -d mysql redis
1b. (可选)逆向方言验证库:PostgreSQL + SQL Server
./scripts/dev-reverse-dbs.sh
或仅 PG:docker-compose --profile reverse up -d postgres
连接见脚本输出;MySQL 验证库 reverse_demo(root/root)
2. 后端(默认端口 9502,profile=dev;tmux 常驻)
./backend/dev-ensure.sh # 幂等:健康秒退,不健康自动拉起 ./backend/dev-ensure.sh --restart # 改了 Java/yml/mapper 后重启 ./backend/dev-ensure.sh --logs # 看启动日志
3. 前端(默认端口 8000)
cd frontend yarn yarn start
4. (可选)自部署同款验收:health/info/前端 + erd Flyway
./scripts/verify-self-deploy.sh
生产 compose 验收与**已有卷升级演练**见 [deployment.md](./deployment.md)。
> 后端不要用 `mvn spring-boot:run` 或在普通 shell 里 `nohup`:IDE/agent 会话结束会杀子进程。`dev-ensure.sh` 把进程托管进 tmux 会话 `erd-be`,终端关闭不影响。依赖:`brew install tmux`。
> Agent/人强制入口见 `.cursor/rules/dev-entrypoints.mdc`:后端只调 `dev-ensure.sh`;前端 `yarn start` 常驻、改代码靠 HMR、禁止为生效而重启。
> 本地 `config.dev.ts` 已设 `mfsu: false`(MFSU eager 曾卡住 build worker / 送旧模块);改该开关后需重启一次 `yarn start`。
> 设计器进版本管理:侧栏「版本 → 版本管理」,或顶栏项目菜单「版本」(均打开 `/design/table/version/all`)。版本页顶栏「返回模型」回 `/design/table/model?projectId=…`(侧栏「模型」常被树遮挡,勿只依赖侧栏)。
## 前端样式(token first)
工作台样式优先 antd 5 **ConfigProvider theme tokens**,少维护散落 less。
| 真相源 | 路径 |
|---|---|
| antd tokens | `frontend/src/theme/tokens.ts` → `components/Theme`(`ConfigProvider`) |
| CSS 变量(与上同值) | `frontend/src/theme/css-vars.less`(由 `global.less` 引入) |
布局 chrome(Home/Group/Design 已 BEM + `var(--erd-*)`;`account/settings` 仍挂 ProLayout);**落地页** `pages/landing/index.less` 保留深色门面 scoped less,但色/字已读 `--erd-*`(禁止再发明第二套色板)。新颜色/圆角先改 `tokens.ts`。细则见 [ui-home-model-redesign.md](./ui-home-model-redesign.md)#样式策略token-first。
## 前端单测(轻量)
`max test` 依赖的 PuppeteerEnvironment 已不可用;画布 undo 栈用:
```bash
cd frontend && yarn test:unit:canvas-history
E2E(Playwright)
cd frontend
yarn test:e2e # 全量(chromium + chromium-serial;无 project deps,可并行)
yarn test:e2e:serial # 仅串行项目(activation / 空态 / export-feedback)
PW_WORKERS=16 yarn test:e2e # 拉满并行段(需 16 核级机器)
# 单条并行用例
npx playwright test tests/e2e/smoke.spec.ts --project=chromium --grep '关键字'
# 单条串行用例(勿漏 --project=chromium-serial;workers=1 已在 config,无需 --no-deps)
npx playwright test tests/e2e/activation.spec.ts --project=chromium-serial --grep '关键字'
- 并发隔离:本地上限 16 worker(默认
ceil(CPU/2),满配PW_WORKERS=16);每 worker 登录e2e{n}(e2e0..e2e15);项目名e2e-w{n}-前缀 - 空态/示例/导出失败用例在
chromium-serial(config 内workers: 1,账号e2e-serial);不要给该 project 配dependencies: ['chromium'](曾导致--project=chromium-serial先跑完整套 chromium);CI 全量顺序见e2e-smoke.yml两步 - E2E / 公开 demo 种子:空卷由后端 Flyway
V5/V6写入;已有库可./backend/dev-ensure.sh --restart或查flyway_schema_history - 改公开/登录示例模型:先改
schema/examples/demo.projectjson.json,再node scripts/sync-demo-projectjson.mjs,再确保 FlywayV5已应用(或对新库重建卷) - 后端
dev打开erd.security.e2e-accounts-enabled;prod拒绝e2e\\d+/e2e-serial登录 - 定位优先级见
.cursor/rules/e2e-locators.mdc:getByRole→ label/placeholder →getByTestId;禁止.ant-*
Schema 双源(db/init vs Flyway)
| 来源 | 路径 | 职责 |
|---|---|---|
| 空卷首启(schema-only) | db/init/01_create_database.sql + 02_tables.sql | MySQL 空 data 卷首次挂载执行;只建库 + CREATE TABLE(ADR-0020) |
| 增量 schema 与种子 | backend/src/main/resources/db/migration/erd/(V*__*.sql) | ErdFlywayConfig 打到单一业务库;新变更只写这里 |
约定:
db/init禁止再加种子 / privileges;日常增量只加 FlywayV*__*.sql- 配置:
spring.flyway.enabled=false;ErdFlywayConfig绑erdDataSource(与系统 DS 同库) - 从旧双库升级:见 ADR-0020「后果」;本地最快路径
docker compose down -v && docker compose up -d - 改迁移后:
./backend/dev-ensure.sh --restart(pom 变更先刷新target/cp.txt)
文档站(Docusaurus)
cd website && yarn && yarn start # http://localhost:3000/erdonline/
cd website && yarn build # 产物 website/build;死链会失败
消费仓库 docs/(ADR-0003)。本地中文搜索:@easyops-cn/docusaurus-search-local(需 yarn build && yarn serve 验证索引;dev 下索引可能不全)。
CI:.github/workflows/docs-site.yml(PR 构建;main → GitHub Pages 且(若已配 secrets)Cloudflare Pages erdonline-docs)。
回退:无 CLOUDFLARE_* secrets 时仅 GH Pages。仓库 Settings → Pages → Source 选 GitHub Actions。
静态 demo:.github/workflows/frontend-demo-site.yml → CF 项目 erdonline-demo(见 deployment.md 托管拓扑)。
协作 Presence(SocketIO)
- 端口
9092(netty-socketio,与 HTTP9502分离);前端SOCKETIO_URL(dev 默认http://localhost:9092) - 握手:先
POST /auth/socket-ticket(Bearer JWT)拿短票,再连 namespace/project/erd(query 须带真实projectId;用户须 ∈project_user,见 ADR-0009 / R-AUTH-05) - 验证:
node scripts/verify-socket-presence.mjs;verify-socket-cursor.mjs;verify-socket-sync.mjs;负向verify-socket-membership.mjs;E2Epresence.spec.ts
projectJSON schema(agent 可读)
对外规范:data-format.md。改 schema/projectjson.schema.json 或示例后:
node scripts/validate-projectjson.mjs
# 或:cd frontend && yarn validate:projectjson
前端如何找到后端
前端通过 frontend/config/proxy.ts 在开发环境把 /api、/ncnb、/auth 代理到 http://localhost:9502。
JWT 含全量权限时 Authorization 头可达 8KB+;Boot 3 须配置 server.max-http-request-header-size(本仓 64KB,见 ADR-0015)。若写接口返回 HTML 400,先查该配置是否生效(./backend/dev-ensure.sh --restart),再查代理是否把 SPA HTML 误回给 /ncnb/*。
后端 GatewayPrefixStripFilter 剥离 /ncnb|/auth|/syst 前缀后再进 Controller。
生产环境通过 public/env-config.js(由 .env 生成)注入 window._env_.API_URL。
联调探测(登录后打常用接口,期望无 404/405/500):
./scripts/audit-fe-apis.sh
# 或指定:./scripts/audit-fe-apis.sh http://localhost:9502 e2e0 123456
后端包结构
com.erdonline
├── ErdOnlineApplication # 启动类
├── auth/ # OAuth2
├── system/ # 用户/权限/菜单/字典
├── erd/ # 建模核心
├── common/ # 公共库
└── config/ # 全局配置