Skip to content

环境准备与启动 ​

适用端:后端 + Web | 类型:操作

从零把后端 ainb 与 Web 前端 ainb-ui-admin-vue3 在本地跑起来,并给出「跑通了没有」的判定方法。本页所有命令与输出都在 Windows 10 + Git Bash 环境实测过。

移动端不在这页

移动端 ainb-ui-admin-uniapp 的启动路径(H5 :9000 / 微信小程序 / App)、env/.env* 叠加顺序与「只能 pnpm」的约束单独成页:移动端环境准备与启动。它共用本页第一步的同一个后端与同一个库,所以先把后端跑起来再去看那页。

前置阅读:手册导读(先搞清楚三个仓库分别是什么)。

它解决什么问题 ​

本地开发链路只有四段,任何一段没对上都会表现为「前端白屏」或「接口 401」:

前端不走 Vite proxy

vite.config.ts 的 server.proxy 整段是注释掉的(注释原文:「server 端已经支持跨域」)。浏览器直连 http://localhost:48080/admin-api,base_url 由 .env.local 的 VITE_BASE_URL + VITE_API_URL 拼成。所以「后端换了端口」只需要改 .env.local,不要去 vite.config.ts 里找 proxy。

需要装什么 ​

组件版本要求出处 / 实测
JDK编译目标 17根 pom.xml 的 <java.version>17</java.version>;实测用 BellSoft Liberica JDK 21 编译通过(maven.compiler.target=17)
Maven3.6+实测 3.9.16。仓库没有 mvnw,只能用 PATH 上的 mvn
Node.js≥ 20.19.0前端 package.json 的 engines.node
pnpm≥ 8.6.0前端 package.json 的 engines.pnpm。只能用 pnpm,npm i / yarn 会破坏 lockfile
MySQL8.xscript/docker/docker-compose.yml 用 mysql:8;sql/tools/docker-compose.yaml 用 mysql:8.0.33
Redis6+docker-compose.yml 用 redis:6-alpine;spring.cache.type: REDIS 是硬依赖,没有 Redis 起不来

不需要装的东西(容易白折腾):Nacos(全仓 pom 零命中)、XXL-Job(定时任务用的是 Quartz,且 local profile 直接 exclude 了 QuartzAutoConfiguration)、对象存储(infra 文件服务可用本地磁盘/数据库)、RocketMQ / Kafka(WebSocket 的 sender-type: local)。

第一步:准备数据库 ​

库名是 ainb-professional-init(application-local.yaml:53 与 application-dev.yaml:53 里写死的),字符集 utf8mb4。库名带连字符,连接串里原样写着,命令行里要引号。

prod profile 还指着旧库名

application-prod.yaml:54,75 仍然是 ruoyi-vue-pro,没有跟着 local / dev 一起改(local 由 5b955cb8a7 改、dev 由 c3dccc1a82 改)。按 prod 配置部署时,那个库里没有 system_nav_node,「App菜单」页与 GET /system/nav-node/tree 会直接报表不存在。部署前先确认目标库名。

ainb/sql/mysql/ 下现在只有 4 个 .sql,外加一个 update/ 目录(实测 2026-10-25):

文件大小建表数作用
ainb-professional-init.sql39 MB211专业版全量快照,Source Schema: ainb-professional-init。含 agent_ 16 / ai_ 13 / bpm_ 12 / infra_ 24 / biz_ 9 / test_ 39 / act_ 39 / qrtz_ 11。唯一能把平台跑起来的一份
ainb-init.sql13 MB95开源版全量快照,Source Schema: ainb-public-init。只有 system_ 34 / infra_ 7 / act_ 39 / flw_ 6 / sys_ 7 / graph_ 2
ruoyi-vue-pro.sql1.9 MB48上游芋道基线(system_ 32 / infra_ 11 / 示例表 5),只作对照,不要导
quartz.sql42 KB11Quartz 表。专业版快照里已含 qrtz_ 11 张,不需要再导
update/*.sql6 个—增量迁移脚本,见下文导入顺序

两份 dump 在 nav-node 这件事上正好是反的

  • ainb-init.sql(开源版)有 system_nav_node 的建表与 9 行「App菜单」菜单/权限,但没有 infra_form_design.app_nav_node_id 列,且缺 64 张代码里 @TableName 声明了的表 —— 包括 infra_codegen_table / infra_codegen_column,连代码生成器自己都不能用;AI、Agent、工作流、低代码全部起不来。
  • ainb-professional-init.sql(专业版)平台表齐全,但完全没有 nav-node 相关的任何东西:既没有 system_nav_node 建表,也没有那 9 行菜单,只有一处手工加的 app_nav_node_id 列(:14270),而它自己的注释还引用着那张不存在的表。

所以「导开源版」和「导专业版」都不能一步到位。

导入(Git Bash,在 ainb/ 目录下执行):

bash
mysql --default-character-set=utf8mb4 -h127.0.0.1 -uroot -p123456 \
  -e "CREATE DATABASE IF NOT EXISTS \`ainb-professional-init\` DEFAULT CHARACTER SET utf8mb4"
mysql --default-character-set=utf8mb4 -h127.0.0.1 -uroot -p123456 ainb-professional-init \
  < sql/mysql/ainb-professional-init.sql

# 再按【依赖顺序】补 nav-node 那 6 个增量脚本。
# 🔴 不能写 for f in sql/mysql/update/*.sql —— 通配按字母序展开,会让
#    menu-manage-split-web-app.sql 跑在它自己声明的前置之前、
#    nav-node-prune-undelivered.sql 跑在它要裁的 seed 之前。
U=sql/mysql/update
for f in $U/2026-10-24-system-nav-node.sql \
         $U/2026-10-24-system-nav-node-seed.sql \
         $U/2026-10-24-nav-node-prune-undelivered.sql \
         $U/2026-10-24-system-nav-node-menu.sql \
         $U/2026-10-24-menu-manage-split-web-app.sql \
         $U/2026-10-24-form-design-app-nav.sql; do
  mysql --default-character-set=utf8mb4 -h127.0.0.1 -uroot -p123456 ainb-professional-init < "$f"
done

这 6 个脚本都写成幂等的(按语义键先删后插,或用 CREATE TABLE IF NOT EXISTS),可以重复执行。没有 Flyway / Liquibase / spring.sql.init,全靠人工跑一次。跑完后端要重启:GrantDecisionService#resourceChainCache 是进程级缓存且没有 TTL,sys_resource 与菜单的迁移不重启不生效。

已经有跑着的库就别重导

全量快照重导等于把演示数据、菜单授权全部打回快照状态。本手册的截图与示例数据都建立在现有库上,重导后需要重新跑 xpy-blog/tools/seed-*.mjs 系列夹具才能复现。

第二步:确认后端配置 ​

配置文件在 enlev-server/src/main/resources/,一共 5 个:application.yaml(公共)+ application-{local,dev,prod}.yaml + logback-spring.xml。application.yaml 里 spring.profiles.active: local,所以本地开发只需要看 application-local.yaml。

需要确认的四处:

配置项local 的值说明
spring.datasource.dynamic.datasource.master.urljdbc:mysql://127.0.0.1:3306/ainb-professional-init?...库名 / 地址 / 账号密码在这里改
spring.datasource.dynamic.datasource.slavelazy: true,同库同账号多数据源用 dynamic-datasource,primary: master;slave 是懒加载,不连也不报错
spring.data.redishost: 127.0.0.1 / port: 6379 / database: 0password 行是注释掉的
server.port48080注意:不在 application.yaml,三个 profile 文件各写一份

local profile 还关掉了几个碍事的东西(都是本项目本地开发的默认取向,照抄即可):

yaml
spring:
  autoconfigure:
    exclude: # 排除 Quartz 与向量库自动配置,本地起不来也不需要
      - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration
enlev:
  captcha:
    enable: false # 关图片验证码,方便脚本登录
  security:
    mock-enable: false # 模拟登录,三个 profile 都关着(见下文「免登录调试」)
  access-log:
    enable: false

第三步:起后端 ​

IDE 里直接跑主类 enlev-server/src/main/java/cn/enlev/ainb/server/EnlevServerApplication.java(@SpringBootApplication(scanBasePackages = {"${enlev.info.base-package}.server", "${enlev.info.base-package}.module"}),enlev.info.base-package = cn.enlev.ainb)。

命令行则用 Maven:

bash
cd ainb
mvn -pl enlev-server -am -DskipTests spring-boot:run

只想验证某一层能不能编过,用增量编译(实测 18.6 秒,本地仓库已暖):

bash
mvn -q -pl enlev-module-system -am -DskipTests compile

-pl <模块> -am 会连带编译它依赖的上游模块。注意业务模块只有 5 个(enlev-module-{system,infra,bpm,ai,agent}),上游的 enlev-module-im、支付、商城、CRM 等已连目录一起删除,-pl enlev-module-im 必然报「Could not find the selected project in the reactor」。

第四步:起前端 ​

bash
cd ainb-ui-admin-vue3
pnpm install
pnpm dev

pnpm dev 实际是 vite --mode env.local,加载 .env + .env.local,端口 VITE_PORT=80,host: 0.0.0.0,open: true(自动开浏览器)。访问 http://localhost,登录页默认已填好租户「启凌智搭」与账号 admin(来自 .env 的 VITE_APP_DEFAULT_LOGIN_*),本地验证码已关闭。

pnpm dev-server 连的不是你的后端

dev-server = vite --mode dev,.env.dev 里 VITE_BASE_URL='http://api-dashboard.enlev.cn'——那是远端环境。用它验证本地后端改动,看到的是别人的数据。

验证跑通了 ​

检查命令期望
后端活着curl -s http://127.0.0.1:48080/admin-api/system/auth/get-permission-info{"code":401,"msg":"账号未登录"}(401 说明服务通了,只是没带 token)
接口文档浏览器打开 http://127.0.0.1:48080/doc.htmlknife4j 页面,HTTP 200
前端活着浏览器打开 http://localhost登录页
全链路用 admin / admin123 登录进首页,左侧菜单完整

接口文档的分组是按模块的 GroupedOpenApi bean 来的,实测 http://127.0.0.1:48080/v3/api-docs/swagger-config 返回:

json
{"urls":[{"url":"/v3/api-docs/ai","name":"ai"},{"url":"/v3/api-docs/all","name":"all"},
         {"url":"/v3/api-docs/bpm","name":"bpm"},{"url":"/v3/api-docs/infra","name":"infra"},
         {"url":"/v3/api-docs/system","name":"system"}]}

没有 agent 分组

enlev-module-agent 是自研模块,没有写 AgentWebConfiguration,因此 97 个 /admin-api/agent/** 接口不会出现在独立分组里,只能在 all 组找到(实测 all 组含 99 条 agent 路径)。这不是接口没注册,是文档分组缺一个 bean——补法见接口约定与 CRUD 骨架。

免登录调试:mock token ​

enlev-spring-boot-starter-security 里有一套 mock 登录:TokenAuthenticationFilter#mockLoginUser 校验 token 以 mockSecret 开头,截掉前缀当 userId,租户取请求头 tenant-id。开着的时候,Authorization: Bearer test + 用户编号 就能直接冒充任意用户,无需走登录接口:

bash
curl -s -H "Authorization: Bearer test1" -H "tenant-id: 1" \
  http://127.0.0.1:48080/admin-api/system/user/profile/get
# {"code":0,"msg":"","data":{"id":1,"username":"admin","nickname":"超级管理员",...}}

三个 profile 现在都是 mock-enable: false

application-{local,dev,prod}.yaml 全部显式关掉了(476b4b2637,2026-10-18)。上面那条 curl 现在会返回 401,本手册的 tools/ 脚本也全走真实登录取 token。 原因是这个口子的代价太大:SecurityProperties 的 mockSecret 默认值就是 "test",而 mockEnable 默认 false 只说明「不配就不开」,一旦有人图省事打开、又忘了配 mock-secret,任何能连到 48080 的人都能用 Bearer test1 拿到超级管理员身份 —— prod 曾长期处在这个状态。TokenAuthenticationFilter#mockLoginUser 的方法注释原文是「注意,在线上环境下,一定要关闭该功能!!!」。 真要临时用:把 mock-enable 改 true 的同时必须配一个不可猜的 mock-secret,且只在 local 改、不要提交。

常用命令速查 ​

目的命令在哪执行
编译单模块(含依赖)mvn -q -pl enlev-module-system -am -DskipTests compileainb/
打可执行 jarmvn -DskipTests package → enlev-server/target/enlev-server.jar(fat jar,340 MB;全量无改动实测 12.9 秒 BUILD SUCCESS,24 个模块)ainb/
跑全部单测mvn testainb/
前端开发pnpm dev(:80,连本地 48080)ainb-ui-admin-vue3/
前端类型检查pnpm ts:check(脏了用 pnpm ts:check:clean)同上
前端单测pnpm test:unit(vitest,59 个 src/**/*.spec.ts,1280 用例 / 4.14 s)同上
前端生产构建pnpm build:prod → dist-prod/同上
前端 lintpnpm lint(eslint + stylelint + prettier 三连检查)同上

坑与注意 ​

  • .env.local 是纳入 git 跟踪的(不合常理但确实如此)。不要加进 .gitignore,也不要把里面的值搬到别处——它是本地联调的唯一事实来源。
  • src/types/auto-*.d.ts 只由 dev server 生成(build/vite/index.ts 里写的是 dts: !isBuild && '...'),且被 .gitignore 的 auto-*.d.ts 规则忽略。新增全局组件后要先跑一次 pnpm dev 再跑 pnpm ts:check,否则报「找不到组件」。
  • pnpm test:e2e 是坏的:playwright.config.ts 与 tests/e2e/ 都不存在,别运行也别尝试补全。
  • 三个仓库是各自独立的 git 仓库,C:\code\xpy 本身不是仓库。跨端改动要分别提交(一次改动可能要在两三个仓库各提交一次),执行 git 命令前先 cd 进对应子目录。
  • 端口占用:后端 48080、前端 80。Windows 上 80 端口容易被 IIS / 其它服务占,改 .env 的 VITE_PORT 即可(前端直连后端,改端口不影响接口)。
  • 后端启动失败先按顺序排:MySQL 通不通 → 库名是不是 ainb-professional-init → Redis 通不通 → 48080 是否被占。这四条覆盖了绝大多数情况。
  • 起来了但页面报「表不存在」,多半是只导了全量快照、没跑 sql/mysql/update/ 那 6 个增量脚本;表齐了但菜单/权限不对,则是没重启后端(resourceChainCache 无 TTL)。

→ 本节是贴着上下文的提醒;按症状查的全域清单见坑位索引。

相关页面 ​