本文引用的文件
本仓库是一个包含 Java 后端与 Electron 桌面客户端的多模块工程。整体分为三层:
ai-server 与 ai-gateway 两个 Spring Boot 子模块。ai-gateway:基于 Spring Cloud Gateway WebFlux 的转发网关,端口默认 8080。ai-server:业务后端,端口默认 8980,上下文路径 /js/a。开发者通常同时运行 Gateway、ai-server 和 Electron 客户端;运维或打包人员则使用 Maven 构建后端 Jar,并使用 Electron 打包命令生成安装包。
graph TB
Dev["开发者终端"] --> Maven["Maven 父工程<br/>zsjz-ai"]
Dev --> Pnpm["pnpm 前端命令<br/>ai-electron/frontend"]
Dev --> Electron["Electron 客户端命令<br/>ai-electron"]
Maven --> Gateway["ai-gateway<br/>Spring Cloud Gateway<br/>端口 8080"]
Maven --> Server["ai-server<br/>Spring Boot<br/>端口 8980<br/>上下文 /js/a"]
Electron --> Frontend["Vite 前端开发服务器"]
Electron --> Main["Electron 主进程"]
Frontend --> Gateway
Main --> Gateway
Gateway --> Server
图示来源
| 模块 | 类型 | 主要职责 | 关键入口 |
|---|---|---|---|
根目录 pom.xml |
Maven 父工程 | 声明 ai-server、ai-gateway 两个模块 |
mvn 聚合命令 |
ai-gateway |
Spring Boot 子模块 | 按用户粘性路由转发到 ai-server | 端口 8080,上下文路径不强制 |
ai-server |
Spring Boot 子模块 | 业务逻辑、数据库、Redis、向量模型、AI 能力 | 端口 8980,上下文路径 /js/a |
ai-electron |
Electron 客户端 | 桌面应用入口、打包、加密、更新 | package.json scripts |
ai-electron/frontend |
Vue + Vite 前端 | 开发、构建、预览、代码检查 | pnpm dev、pnpm build |
deploy/env.sh |
Bash 环境变量脚本 | 统一设置 ai-server 运行时环境变量 | 通过 source 或 systemd EnvironmentFile 加载 |
cmd/uninstall.* |
卸载脚本 | 清理客户端进程与用户数据目录 | Linux/macOS 用 shell,Windows 用 bat |
章节来源
根 pom.xml 是 Spring Boot Starter Parent 的子工程,类型为 pom,包含两个模块:
| 模块 | groupId | artifactId | 说明 |
|---|---|---|---|
| 父工程 | com.zsjz |
zsjz-ai |
聚合构建,不产 Jar |
| 网关 | com.zsjz |
ai-gateway |
Spring Cloud Gateway WebFlux |
| 后端 | com.zsjz |
ai-server |
业务后端 |
两者都继承 com.zsjz:zsjz-ai:1.0,Java 版本要求为 25。
flowchart TD
Parent["Maven 父工程<br/>zsjz-ai:1.0"] --> GatewayPom["ai-gateway/pom.xml"]
Parent --> ServerPom["ai-server/pom.xml"]
GatewayPom --> GatewayJar["ai-gateway.jar"]
ServerPom --> ServerJar["ai-server.jar"]
图示来源
| 场景 | 命令 | 说明 |
|---|---|---|
| 在父工程构建全部后端 | mvn clean package -DskipTests |
编译并打包 ai-gateway 与 ai-server |
| 仅构建网关 | mvn -pl ai-gateway clean package -DskipTests |
跳过测试,生成 ai-gateway.jar |
| 仅构建后端 | mvn -pl ai-server clean package -DskipTests |
跳过测试,生成 ai-server.jar |
| 本地调试后端 | mvn -pl ai-server spring-boot:run |
以 Spring Boot 方式直接运行 |
| 本地调试网关 | mvn -pl ai-gateway spring-boot:run |
以 Spring Boot 方式直接运行 |
| 只编译不打包 | mvn -pl ai-server,ai-gateway compile |
适合 IDE 同步 |
注意:ai-gateway 在构建阶段会把根目录 sql/gateway.sql 复制到 classpath:db/gateway.sql,因此首次 package 前需要确保该 SQL 文件存在。
java.version=25,父工程与两个子模块均声明此版本。章节来源
前端位于 ai-electron/frontend,使用 pnpm、Vite、Vue 3、TypeScript。
| 命令 | 作用 | 备注 |
|---|---|---|
pnpm bootstrap |
执行 pnpm install 安装依赖 |
预安装脚本强制使用 pnpm |
pnpm dev |
启动 Vite 开发服务器 | 默认监听开发端口,支持热更新 |
pnpm serve |
等同于 pnpm dev |
别名命令 |
pnpm build |
生产构建前端资源 | 启用内存限制,输出到 dist |
pnpm build:tomcat |
构建为 Tomcat 部署模式 | 清空输出目录 |
pnpm preview |
构建后预览生产产物 | 默认端口 3100 |
pnpm type:check |
TypeScript 类型检查 | 不输出文件 |
pnpm lint:all |
安装依赖、类型检查、ESLint、Prettier、Stylelint | 完整代码质量流程 |
pnpm reinstall |
删除锁文件和依赖后重装 | 依赖损坏时可用 |
pnpm uninstall |
删除 node_modules |
清理依赖目录 |
前端引擎要求 Node.js 版本满足 >=20.19 || >=22.12,包管理器锁定为 pnpm 10.25.0。
Electron 客户端位于 ai-electron,其 package.json 提供两类命令:
| 命令 | 作用 | 说明 |
|---|---|---|
pnpm dev |
启动 Electron 开发模式 | 实际调用 ee-bin dev |
pnpm start |
启动已构建的 Electron 客户端 | 实际调用 ee-bin start |
pnpm build |
构建前端、构建 Electron、加密 | 等价于先 build-frontend,再 build-electron,最后 encrypt |
pnpm dev-frontend |
仅启动前端开发服务 | 参数 --serve=frontend |
pnpm dev-electron |
仅启动 Electron 开发服务 | 参数 --serve=electron |
pnpm build-frontend |
构建前端资源 | 调用 ee-bin 并移动前端产物 |
pnpm build-electron |
构建 Electron 部分 | 调用 ee-bin 构建 Electron 层 |
pnpm test |
运行 Vitest 单测 | 使用 electron 相关测试工具 |
pnpm test:watch |
监听模式运行测试 | 开发时调试测试用例 |
pnpm typecheck |
TypeScript 类型检查 | 不输出文件 |
pnpm re-sqlite |
重建 better-sqlite3 原生模块 | 平台变化后可能需要 |
Electron 客户端提供各平台打包命令:
| 命令 | 平台 | 说明 |
|---|---|---|
pnpm build-w |
Windows x64 | 构建 Windows 安装包 |
pnpm build-we |
Windows | 构建 Windows 扩展或增强产物 |
pnpm build-m |
macOS ARM64 | 构建 Apple Silicon Mac 安装包 |
pnpm build-m-x86 |
macOS x86_64 | 构建 Intel Mac 安装包 |
pnpm build-m-arm64 |
macOS ARM64 | 同上,ARM64 专用别名 |
pnpm build-l |
Linux | 构建 Linux 安装包 |
这些命令最终委托给 ee-bin build --cmds=<platform>,由 ElectronEgg 框架完成打包流程。
章节来源
Electron 打包输出目录由 ai-electron/cmd/builder.json 中的 directories.output 指定为 out。也就是说,所有安装包和展开目录都会放在 ai-electron/out 下。
flowchart TD
Build["pnpm build-*"] --> Builder["electron-builder / ee-bin"]
Builder --> OutDir["ai-electron/out"]
OutDir --> WinExe["qingjian-ai-client-win-200.0.0-x64.exe"]
OutDir --> Unpacked["win-unpacked/"]
OutDir --> Latest["latest.yml"]
OutDir --> Config["builder-effective-config.yaml"]
OutDir --> Debug["builder-debug.yml"]
图示来源
Windows 使用 NSIS 打包器,产物包括:
| 产物 | 含义 |
|---|---|
qingjian-ai-client-win-200.0.0-x64.exe |
可分发的安装包 |
qingjian-ai-client-win-200.0.0-x64.exe.blockmap |
增量更新校验文件 |
win-unpacked/qingjian-ai-client.exe |
未打包的可执行程序 |
win-unpacked/resources/app.asar |
应用代码包 |
win-unpacked/resources/app-update.yml |
自动更新配置 |
win-unpacked/locales/zh-CN.pak |
中文界面语言包 |
latest.yml |
最新版本信息(通用发布) |
NSIS 安装器允许非一键安装、允许提权、允许修改安装目录,并创建桌面快捷方式和开始菜单快捷方式。
deb 包,分类为 Utility。qingjian-ai-client。com.zsjz.qingjian.client。cmd/、data/、electron/、frontend/、logs/、out/、go/、python/ 等目录,避免把源码和中间产物打入安装包。Electron 默认从 file:// 协议加载前端,索引页路径为 /public/dist/index.html。这意味着:
public/dist/index.html。Electron 主窗口启用了 nodeIntegration=true 且关闭 contextIsolation,以便渲染进程直接调用 IPC。
sequenceDiagram
participant User as "用户"
participant Electron as "Electron 主进程"
participant Renderer as "渲染进程"
participant Gateway as "Gateway :8080"
participant Server as "ai-server :8980"
User->>Electron: 启动客户端
Electron->>Renderer: 打开 file:///public/dist/index.html
Renderer->>Gateway: 发起 /js/a 后端请求
Gateway->>Server: 转发到 http://localhost:8980/js/a
Server-->>Gateway: 返回 JSON
Gateway-->>Renderer: 返回响应
Renderer-->>User: 显示界面
图示来源
章节来源
ai-electron/frontend/bin/install.sh 是一个简短的辅助脚本:
ai-electron/frontend 目录。pnpm install。bin 目录。它只是对 cd .. && pnpm install 的封装,方便从 bin 目录直接执行。
ai-electron/frontend/bin/startup.sh 的作用:
ai-electron/frontend 目录。pnpm dev。bin 目录。适合在类 Unix 系统中双击或通过终端快速启动前端开发服务器。
ai-electron/frontend/bin/build.sh 的作用:
ai-electron/frontend 目录。pnpm build。bin 目录。用于在 Linux 或 macOS 上构建前端生产资源。
cmd/uninstall.sh 是 QingJian 客户端的卸载清理脚本,行为如下:
| 步骤 | 行为 |
|---|---|
| 安全检查 | 如果 $HOME 为空,直接报错退出 |
| 终止进程 | 使用 pkill -9 -f "qingjian-client" 强制结束客户端进程 |
| 等待释放 | 若进程被成功终止,等待 2 秒让文件句柄释放 |
| 清理数据目录 | 递归删除三个可能的用户数据目录 |
| 报告结果 | 对每个目录输出是否删除、不存在或权限失败 |
需要清理的目录包括:
| 目录 | 用途 |
|---|---|
$HOME/.config/qingjian-client |
客户端配置目录 |
$HOME/.local/share/QingJian |
客户端共享数据目录 |
$HOME/.qingjian-client |
客户端历史数据目录 |
flowchart TD
Start["执行 uninstall.sh"] --> CheckHome["检查 $HOME 是否为空"]
CheckHome --> HomeEmpty{"$HOME 为空?"}
HomeEmpty -->|是| ExitError["打印错误并退出"]
HomeEmpty -->|否| KillProc["终止 qingjian-client 进程"]
KillProc --> WaitFiles{"是否找到进程?"}
WaitFiles -->|是| Sleep["等待 2 秒释放文件句柄"]
WaitFiles -->|否| SkipKill["提示未发现进程"]
Sleep --> CleanDirs["遍历并删除用户数据目录"]
SkipKill --> CleanDirs
CleanDirs --> Done["输出清理完成"]
图示来源
cmd/uninstall.bat 是 Windows 平台的卸载脚本。虽然当前仓库内容无法以 UTF-8 正常读取,但从命名和位置可以确定其用途是配合 Windows 客户端进行卸载或清理操作。实际使用时应通过管理员终端或右键“以管理员身份运行”执行,以避免权限不足。
章节来源
ai-server/src/main/resources/application.yaml 中的配置项大多采用 ${ENV_NAME:默认值} 的形式。例如:
app.cors.enabled=${APP_CORS_ENABLED:true}spring.task.scheduling.pool.size=${SPRING_TASK_SCHEDULING_POOL_SIZE:4}spring.servlet.multipart.max-file-size=${SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE:200MB}这意味着:环境变量优先级高于 YAML 默认值。如果设置了同名环境变量,Spring Boot 会优先使用环境变量值。
deploy/env.sh 是专门为 Linux 部署设计的后端环境变量脚本。它的核心作用有三点:
application-dev.yaml 的开发环境行为保持一致。source,也可以作为 systemd 的 EnvironmentFile。脚本注释明确指出:端口 8980、上下文路径 /js/a、应用名 ai-server 是硬编码在 application.yaml 中的,不参与环境变量参数化,因此不会出现在 env.sh 中。
脚本文档给出两种标准用法:
| 场景 | 用法 |
|---|---|
| 手动启动 | set -a; source deploy/env.sh; set +a,然后 java -jar ai-server.jar |
| systemd 服务 | 在单元文件中添加 EnvironmentFile=/opt/zsjz-ai/deploy/env.sh |
set -a 的作用是使后续赋值自动导出为环境变量,set +a 恢复默认行为。这样 source 后执行的 java -jar 就能读到这些变量。
| 类别 | 示例变量 | 说明 |
|---|---|---|
| 跨域 | APP_CORS_ENABLED、APP_CORS_ALLOWED_ORIGIN_PATTERNS |
桌面客户端通过 file:// 加载前端,必须允许跨域 |
| Spring 基础 | SPRING_TASK_SCHEDULING_POOL_SIZE、SPRING_HTTP_CODECS_MAX_IN_MEMORY_SIZE |
控制调度线程池、HTTP 大小限制 |
| PostgreSQL | SPRING_DATASOURCE_DYNAMIC_* |
平台数据库连接,必须安装 pgvector 扩展 |
| Redis | SPRING_DATA_REDIS_HOST、SPRING_DATA_REDIS_PORT |
sa-token 登录态硬依赖 |
| Elasticsearch | SPRING_ELASTICSEARCH_* |
全文检索,可选鉴权用户名密码 |
| 本地存储 | STORAGE_LOCAL_ROOT_PATH、STORAGE_LOCAL_BASE_URL |
相对 JVM 工作目录 |
| Neo4j | NEO4J_URI、NEO4J_USERNAME、NEO4J_PASSWORD |
可选图谱能力 |
| RAG | ETL_RAG_ENABLED、ETL_RAG_TOP_K、ETL_RAG_SCORE_THRESHOLD |
Agent 表结构语义检索 |
| AI 研判 | ZSJZ_INSIGHT_* |
会话数、保留天数、消息分页等 |
| DuckDB | ZSJZ_DUCKDB_* |
案件库并发、内存比例、回收间隔 |
| 文件 AI | ZSJZ_FILE_AI_* |
非表格文件 AI 识别并发与超时 |
| 向量模型 | ZSJZ_EMBEDDING_* |
本地 ONNX 模型开关、路径、维度、批大小 |
| AI 清洗 | ZSJZ_AI_CLEAN_* |
模板向量索引、重建策略、召回阈值 |
| 对话附件 | ZSJZ_CHAT_ATTACHMENT_* |
文档大小、分块、RAG 召回 |
| 登录安全 | ZSJZ_AUTH_IN_USE_WINDOW_MINUTES |
“账号正在使用”判定窗口 |
flowchart TD
EnvFile["deploy/env.sh<br/>环境变量定义"] --> Shell["shell 或 systemd 注入"]
Shell --> SpringBoot["Spring Boot 应用启动"]
SpringBoot --> Yaml["application.yaml<br/>${ENV_NAME:默认值}"]
Yaml --> EffectiveConfig["最终生效配置"]
ExternalDb["PostgreSQL / Redis / Elasticsearch / Neo4j"] --> EffectiveConfig
图示来源
脚本注释明确要求:
chmod 600,即只有所有者可读。SPRING_PROFILES_ACTIVE 默认不启用生产 profile,可通过取消注释改为 pro。章节来源
推荐使用 Git 克隆仓库,并在 dev_4 分支上工作。克隆后进入仓库根目录执行后续命令。
后端使用 Maven 管理依赖。推荐在仓库根目录执行:
mvn clean package -DskipTests
这会构建 ai-gateway 和 ai-server。如果只想构建其中一个模块,可以使用 -pl 参数。
前端位于 ai-electron/frontend,必须使用 pnpm:
cd ai-electron/frontend
pnpm bootstrap
或直接执行:
pnpm install
Gateway 默认端口 8080,需要先启动 ai-server,再启动 Gateway,因为 Gateway 会转发到 ai-server。
mvn -pl ai-server spring-boot:run
然后另一个终端启动 Gateway:
mvn -pl ai-gateway spring-boot:run
或者先生成 Jar 后运行:
mvn -pl ai-server,ai-gateway package -DskipTests
java -jar ai-server/target/ai-server.jar
java -jar ai-gateway/target/ai-gateway.jar
ai-server 默认端口 8980,上下文路径 /js/a。生产或 Linux 部署时建议先加载环境变量:
set -a
source deploy/env.sh
set +a
java -jar ai-server/target/ai-server.jar
如果不需要自定义环境变量,可以直接运行 Jar 文件。
Electron 客户端有两种开发模式:
cd ai-electron
pnpm dev
这会根据 ElectronEgg 框架启动前后端联合开发流程。
cd ai-electron/frontend
pnpm dev
cd ai-electron
pnpm dev-electron
cd ai-electron/frontend
pnpm build
cd ai-electron
pnpm build-w
产物位于 ai-electron/out/qingjian-ai-client-win-200.0.0-x64.exe。
Apple Silicon:
cd ai-electron
pnpm build-m
Intel Mac:
cd ai-electron
pnpm build-m-x86
cd ai-electron
pnpm build-l
产物通常是 deb 包,位于 ai-electron/out。
flowchart TD
Clone["git clone 仓库"] --> Backend["Maven 构建后端"]
Clone --> Frontend["pnpm bootstrap"]
Backend --> RunServer["启动 ai-server"]
Backend --> RunGateway["启动 ai-gateway"]
Frontend --> RunClient["启动 Electron 客户端"]
RunServer --> Test["浏览器或客户端访问 /js/a"]
RunGateway --> Test
RunClient --> Test
Test --> Package["pnpm build-* 打包安装包"]
[本节为工作流说明,不直接分析具体代码片段]
| 现象 | 原因 | 解决方法 |
|---|---|---|
| ai-server 启动失败 | 端口 8980 已被占用 |
关闭占用端口的进程,或修改 ai-server 的 server.port |
| ai-gateway 启动失败 | 端口 8080 已被占用 |
关闭占用端口的进程,或修改 ai-gateway 的 server.port |
| 前端预览端口冲突 | 预览命令使用 3100 |
修改前端预览端口或关闭占用 3100 的进程 |
| Electron 无法加载页面 | 前端未构建或路径不正确 | 先执行 pnpm build,确保 public/dist/index.html 存在 |
Gateway 默认端口为 8080,ai-server 默认端口为 8980,上下文路径为 /js/a。如果修改了 ai-server 的端口,也要相应调整 Gateway 中 ai-server 节点配置的 base-url。
| 现象 | 原因 | 解决方法 |
|---|---|---|
| Maven 构建失败 | JDK 版本不是 25 |
安装并切换 JDK 25 |
| Maven 无法下载依赖 | 网络或镜像问题 | 配置国内 Maven 镜像或代理 |
| 前端依赖安装失败 | 使用了 npm/yarn 而非 pnpm | 使用 pnpm bootstrap 或 pnpm install |
| 前端报 Node 版本错误 | Node.js 版本不满足 >=20.19 \|\| >=22.12 |
升级 Node.js |
| Electron 原生模块构建失败 | 缺少 Python、C++ 构建工具或平台 SDK | 安装 Electron 原生模块所需构建工具链 |
| SQLite 原生模块构建失败 | 平台变化后 native 模块失效 | 执行 pnpm re-sqlite |
| 现象 | 原因 | 解决方法 |
|---|---|---|
| ai-server 启动时报数据库连接错误 | PostgreSQL 地址、端口、用户名、密码不正确 | 修改 deploy/env.sh 中 PostgreSQL 相关变量 |
| Redis 连接失败 | Redis 不可用或地址端口不一致 | 检查 SPRING_DATA_REDIS_HOST 与 SPRING_DATA_REDIS_PORT |
| Elasticsearch 连接失败 | ES 未启动或 URI 配置错误 | 检查 SPRING_ELASTICSEARCH_URIS |
| Neo4j 连接失败 | Neo4j 未启动或认证失败 | 检查 NEO4J_URI、NEO4J_USERNAME、NEO4J_PASSWORD |
| 向量能力不可用 | 本地模型目录缺失或 pgvector 未安装 | 检查 ZSJZ_EMBEDDING_MODEL_PATH 与 PG 是否安装 pgvector |
Electron 通过 file:// 加载前端,后端独立部署时会触发浏览器跨域限制。如果后端关闭跨域,Electron 客户端将无法获取数据。
解决方法:
APP_CORS_ENABLED=true。APP_CORS_ALLOWED_ORIGIN_PATTERNS 设置为允许的来源,例如固定域名或 *。| 现象 | 原因 | 解决方法 |
|---|---|---|
修改 deploy/env.sh 后无效 |
没有重新 source 或重启服务 |
重新加载脚本并重启 ai-server |
| systemd 服务仍用旧配置 | systemd 缓存或没有重载 | 执行 systemctl daemon-reload 并重启服务 |
| 某些配置仍未覆盖 | 该配置不使用环境变量占位符 | 检查对应 YAML 配置是否确实使用 ${ENV_NAME:默认值} |
| profile 未切换 | 未设置 SPRING_PROFILES_ACTIVE |
取消注释或设置 SPRING_PROFILES_ACTIVE=pro |
| 现象 | 原因 | 解决方法 |
|---|---|---|
pnpm build 找不到前端资源 |
前端未构建 | 先执行 pnpm build-frontend 或 pnpm build |
| Windows 安装包构建失败 | 缺少 NSIS、签名文件或图标 | 检查 build/icons/icon.ico 和相关打包依赖 |
| macOS 打包失败 | 缺少 macOS 签名工具或证书 | 安装 Xcode 命令行工具并配置签名 |
| Linux 打包失败 | 缺少 deb 打包依赖 | 安装 dpkg、fakeroot 等 Linux 打包工具 |
| 输出目录为空 | 构建中途失败 | 查看 ai-electron/out/builder-debug.yml 和控制台日志 |
如果 cmd/uninstall.sh 执行后仍存在残留目录,可能是:
解决方法:
qingjian-client 进程。章节来源
这个项目的构建体系可以概括为:
ai-gateway 与 ai-server,分别负责网关转发和业务逻辑。dev、build、preview 等命令。ee-bin 和 electron-builder 完成前端构建、Electron 构建、加密和各平台打包。deploy/env.sh 集中覆盖 ai-server 的运行时配置,适合 Linux 手动启动和 systemd 部署。典型开发顺序是:先安装 Maven 和 JDK 25,再安装 pnpm 和 Node.js,随后依次启动 ai-server、Gateway 和 Electron 客户端;打包时分别使用 Maven 构建后端,使用 pnpm 命令构建各平台安装包。遇到问题时,应优先检查端口占用、JDK 与 Node 版本、外部中间件连通性、环境变量加载方式以及 Electron 构建日志。