QUICK_START.md 14 KB

清鉴(zsjz-ai)开发快速开始

面向新加入的开发者:从零把后端 ai-server 和前端 ai-frontend 跑起来。 编码约定、分层落位、Agent 子系统等改代码前必读的内容见 AI_AGENT.md,本文只讲「怎么跑起来」。


1. 项目构成

zsjz-ai/
├─ pom.xml              # 父 POM(packaging=pom,Spring Boot 3.5.16),只聚合 ai-server
├─ ai-server/           # 后端:Spring Boot 3 + MyBatis-Plus + AgentScope
├─ ai-frontend/         # 前端:Vue3 + Vite7 + TS + Ant Design Vue(JeeSite 血统)
├─ sql/                 # 建表 / 初始化脚本(手工执行,项目无 Flyway / Liquibase)
├─ QingJian/            # 运行期工作空间资产(conf / db / license / rocksdb / 基站库)
└─ data/files/          # 本地文件存储根目录(storage.local.root-path)

业务闭环:多源数据导入 → 清洗治理(dm)→ 建模分析(话单 / 资金 / 轨迹 / 画像 / 图谱)→ 可视化 → AI 对话式研判。


2. 环境要求

项 版本 校验命令
JDK 25(ai-server/pom.xml 的 java.version) java -version
Maven 3.9.x+ mvn -v
Node >=20.19 \|\| >=22.12(package.json engines) node -v
pnpm 10.x(只能用 pnpm,preinstall: only-allow pnpm) pnpm -v
PostgreSQL 14+,必须装 pgvector 扩展 —
Redis 任意近期版本 —
Elasticsearch 8.18.x(须与 Spring Boot 3.5 托管的客户端版本匹配) —
DuckDB 无需安装,JDBC 驱动内嵌(案件分析库) —
Neo4j 可选,仅在配置图谱能力时需要 —

依赖服务的硬/软关系:

  • Redis 是登录的硬依赖 —— sa-token-redis-jackson 已装配,Redis 不可用则所有 StpUtil.* 抛异常,无降级实现。
  • PostgreSQL(master) 存平台元数据 / Agent 会话 / 模型配置 / 向量,不可用则起不来。
  • Elasticsearch 供 module/search 全文检索(索引 zsjz_search)。
  • DuckDB(slave) 是按案件/工作空间切换的文件库,不是常驻服务。

3. 准备依赖服务

3.1 PostgreSQL

CREATE DATABASE "zsjz-ai";
\c zsjz-ai
CREATE EXTENSION IF NOT EXISTS vector;   -- pgvector,RAG 向量检索必需

连接信息写在 ai-server/src/main/resources/application-dev.yaml:

spring.datasource.dynamic.datasource.master:
  url: jdbc:postgresql://192.168.0.109:5432/zsjz-ai
  username: postgres
  password: postgres
spring.data.redis:      host 192.168.0.109 / port 6379
spring.elasticsearch:   uris http://192.168.0.109:9200

换成自己的本机地址即可(改这一个文件,application.yaml 是公共配置,不要动它的 context-path)。

⚠️ 该文件里存的是内网 IP + 明文口令,只为开发便利。不要把真实凭证提交到公开仓库,也不要在生产 profile 复用 dev 配置。

3.2 Elasticsearch

单机开发用默认 9200 即可。索引 settings 见 ai-server/src/main/resources/es/search-settings.json(单分片 0 副本 + \x1F 分隔符自定义分析器),文档映射见 module/search/domain/SearchDoc.java(索引名 zsjz_search)。

3.3 QingJian 运行期资产

com.zsjz.ai.common.constants.PathConst 以 JVM 工作目录(user.dir)为根,拼出 <user.dir>/QingJian/...,用到:

路径 用途
QingJian/conf/*.json 系统配置 / AI 配置(SystemConfManager 读写)
QingJian/d5e03ad1/ 内置银行卡 BIN、手机号运营商 RocksDB
QingJian/uy76tkp8/data.db RogueMap 数据
QingJian/db/5w8mf4kf 基础案件库模板;db/temp 临时案件库
QingJian/w6df89sk/ 基站库 cellinfo.bin + libCell.dll/.so(JNI)
QingJian/license/ 授权文件 license.xlts 与 regInfo 工具
QingJian/agent/skills/ Agent 技能文件

.gitignore 里 /QingJian/ 被忽略,这些资产不在版本库中,新环境需找同事单独拷贝;缺了它们启动后置任务(AppLoadEndEventListener 初始化 RocksDB / 基站库)会失败。


4. 初始化数据库

项目没有自动建表机制,sql/ 下只有部分脚本,需手工执行:

脚本 目标库 内容
sql/user.sql PostgreSQL(master) sys_user + 案件归属迁移,幂等可重复执行
sql/insight_agent_tables.sql PostgreSQL(master) agent_insight_session / agent_insight_message
sql/insight_agent_tables_align.sql PostgreSQL(master) 上表的约束/索引补丁
sql/plat.sql 平台库 平台元数据表(table_info / table_field / case_info / bank_card_issuer_info …),含 Solon 时代的 chat_* 旧表,与当前 agent_* 实体不完全对应
sql/external_tables.sql / external_table_field.sql 案件库(DuckDB) + 元数据 13 张外部数据表建表 + table_info/table_field 登记
sql/case_table*.sql、create_table_2.sql、table_data_1.sql 案件库(DuckDB) 案件业务表与初始配置
# 平台库(PostgreSQL)
psql -h <host> -U postgres -d zsjz-ai -f sql/user.sql
psql -h <host> -U postgres -d zsjz-ai -f sql/insight_agent_tables.sql
psql -h <host> -U postgres -d zsjz-ai -f sql/insight_agent_tables_align.sql

初始账号(sql/user.sql 内置,BCrypt 哈希):admin / admin123,首次登录后立刻改密。

⚠️ 已知缺口(搭建新环境前必读):agent_chat_session、agent_message、agent_model、agent_model_provider、rag_index_status 等当前 Agent 实体对应的平台表,在 sql/ 下没有完整建表脚本。AI_AGENT.md §11.8 记录:开发库 zsjz-ai 缺平台库结构(平台表在另一套 etl-2 库),裸跑会在启动后置任务阶段报 PSQLException: 关系 "table_info" 不存在。 新环境请从已有可用环境导出平台库结构(pg_dump --schema-only)后再启动,别指望 sql/ 目录自带全套。 改表结构时务必补 sql/ 脚本,并同步 table_info / table_field 元数据三表链路。


5. 启动后端

cd E:/workspace/zsjz-ai        # ★ 工作目录必须是仓库根,PathConst 才命中 QingJian/

mvn -pl ai-server -am clean compile        # 编译
mvn -pl ai-server spring-boot:run          # 运行
mvn -pl ai-server test                     # 跑测试
mvn -pl ai-server -am clean package -DskipTests   # 打包

IDEA 里直接跑 com.zsjz.ai.App,把 Working directory 设为仓库根目录(默认是模块目录,会导致 QingJian 资产与 ./data/files 落点不对)。

上面四条命令都在仓库根执行;cd ai-server 后单模块构建也能解析到父 POM,但打包/运行时的相对路径(QingJian/、./data/files)会跟着工作目录走,所以统一在根目录执行更省心。

启动后:

curl http://localhost:8980/js/a/sys/health     # 免登录健康检查

关键地址(server.port=8980,server.servlet.context-path=/js/a):

端点 说明
POST /js/a/auth/login 登录,返回 token;body: {username, password} 明文 JSON
GET /js/a/sys/health 就绪探测(白名单,免登录)
GET /js/a/mcpsse MCP SSE 端点(白名单、无鉴权,见 §7)
POST /js/a/chat/stream Agent 对话 SSE

生效配置只有 application.yaml + application-dev.yaml(resources 下没有别的 yaml)。 context-path 必须写成 /js/a(以 / 开头、不能以 / 结尾),原 Solon 写法 !/js/a/ 会让 Tomcat 直接抛 IllegalArgumentException 起不来。

模型 / API Key 配置在哪

Agent 用的模型与厂商信息存平台库 agent_model / agent_model_provider,通过前端「模型管理」界面(后端 module/agent 的 /models/**)维护,不是写在 yaml 里。想跑通 AI 研判,先在这个界面上配好一个可用的 Provider(DashScope / OpenAI 兼容 / Ollama,三套 AgentScope 扩展都已在 pom 引入)。


6. 启动前端

cd ai-frontend
pnpm install            # = pnpm bootstrap
pnpm dev                # http://localhost:3100

.env 与 .env.development 关键项(默认值已可用):

VITE_PORT = 3100                                            # dev server 端口
VITE_PROXY = [["/js","http://127.0.0.1:8980/js",false]]      # 代理到本地后端
VITE_GLOB_API_URL_PREFIX = /js
VITE_GLOB_ADMIN_PATH = /a

后端换地址时只改 VITE_PROXY 一行(不能换行)。浏览器打开 http://localhost:3100,用 admin / admin123 登录。

日常命令:

pnpm type:check       # vue-tsc --noEmit
pnpm lint:eslint      # 自动修复
pnpm lint:all         # 全量(含 install)
pnpm build            # 生产构建(--mode production)
pnpm build:tomcat     # tomcat 模式,输出到 .env.tomcat 的 VITE_OUTPUT_DIR
pnpm preview:dist     # 预览构建产物 :3100

.npmrc 里配了 @jeesite 私有源;装不动私有包时先确认网络/镜像可达。


7. 联调要点(改接口前必看)

  1. 路径三段式:请求最终落到 /js/a/... = urlPrefix(/js) + adminPath(/a) + 后端 context-path。前端 defHttp 自动补 /js,代码里写 url: adminPath + '/xxx';不走 defHttp(fetch / <img src>)时手动拼 glob.apiUrl + glob.urlPrefix + glob.adminPath + path。这三处必须同步改。
  2. 鉴权只认请求头:Sa-Token 配的是 token-name: x-token、is-read-cookie: false(仅 Header)。defHttp 自动注入;fetch 场景要手动带 'x-token': getToken()。原生 EventSource 无法自定义请求头,SSE 一律用 fetch + body.getReader() 读增量。
  3. 未登录返回 HTTP 200 + body.code = 401(不是 HTTP 401),前端据此跳登录页。
  4. 两套响应形态:module/agent 的 /chat/**(含 /chat/results/**)是裸返回,调它们必须传 { isTransformResponse: false };/models/** 是 Result<T> 包装,用默认 transform。
  5. 同账号不允许多端登录(is-concurrent: false),后登录顶掉前登录 —— 两个浏览器窗口同时登录,前一个会 401,这是设计行为不是 bug。
  6. MCP 端点无鉴权:/mcpsse、/mcp/message、/mcpstreamable 在 sa-token 白名单里(外部 MCP 客户端不带 x-token)。代价是能访问 8980 端口的人即可读取全部案件数据,非可信网络部署必须在外层(反代/防火墙)限来源。
  7. LicenseFilter 当前是透传实现,授权校验下沉在 SystemService 的 /sys/info、/sys/checkAuth。它被 Spring 自动注册为 /* 全局过滤器,doFilter 里的 chain.doFilter 绝不能删 —— 删了表现为所有接口返回 200 + Content-Length: 0 空白,连 404 都没有,日志无异常。

8. 新页面 / 新接口常见坑

  • 菜单图标不显示:uno.config.ts 的 content.pipeline.include 只扫 **/*.{vue,tsx,ts},menu.json 不在扫描范围,而 Icon 组件是运行时拼 i-<collection>:<name> 类名的 → 新图标要把完整 i- 类名加进 uno.config.ts 的 safelist。
  • 路由不生效:优先在 src/core/router/helper/routeHelper.ts 的 explicitDynamicViewMap 加显式映射,默认的 import.meta.glob('**/views/**') 会命中 node_modules 里的同名 views。
  • Mapper XML 命名空间:必须是 com.zsjz.ai.*。历史上包名迁移漏改 XML(com.qingjian.*)会让 MyBatis 启动即炸。
  • 改后端 DTO 字段 → 同步前端 src/<domain>/api/types/{dto,query}.ts。
  • 新增 Agent 工具 → 写清 @Tool(description=...) / @ToolParam,并同步更新 AgentToolRegistryTest#TOTAL_BUSINESS_TOOLS 的数量断言。

9. 提交前检查清单

# 后端
mvn -pl ai-server -am clean compile
# 前端
cd ai-frontend && pnpm type:check && pnpm lint:eslint
  • 接口字段变更 → 后端 DTO/VO 与前端 TS 类型同步
  • 表结构变更 → sql/ 补脚本 + table_info / table_field 元数据同步
  • 用户级资源接口 → 带 StpUtil.getLoginIdAsLong() 归属校验
  • 无密钥 / 真实库密码 / 内网地址入库
  • 中文注释齐全,无 System.out.println 残留

10. 故障排查速查

现象 原因 / 处置
启动即 ContextPath must start with '/'... application.yaml 的 context-path 被改成了 !/js/a/ 或带尾斜杠 → 改回 /js/a
Failed to parse mapping resource: mappers/... XML 的 namespace/resultType 仍是 com.qingjian.* → 改 com.zsjz.ai.*
PSQLException: 关系 "table_info" 不存在 平台库结构未导入(见 §4 已知缺口)
登录必失败 / 所有 StpUtil 抛异常 Redis 不可达(硬依赖,无降级)
所有接口返回空白 200 LicenseFilter.doFilter 漏了 chain.doFilter
前端请求 404 /js 代理指向错、或后端 context-path 与前端 urlPrefix+adminPath 不一致
SSE 收不到 / 401 用了原生 EventSource(带不了 header),或漏传 isTransformResponse:false
MCP 客户端连不上 spring.ai.mcp.server.base-url 未与 context-path(/js/a)对齐,/mcp/message 会 404
菜单图标缺失 图标类名未进 uno.config.ts 的 safelist
npm install 被拒 项目 preinstall: only-allow pnpm,只能用 pnpm
上传大文件失败 max-file-size: 200MB / max-request-size: 500MB(application.yaml)

11. 延伸阅读

文档 说明
AI_AGENT.md 仓库级编码约定:分层落位、命名规范、Agent 工具清单与硬约束、前后端渲染契约
ai-server/CODE_WIKI.md 模块级说明,⚠️ 部分章节仍是 Solon / com.qingjian 时代内容(app.yml、contextPath !/js/a/、启动类 Solon.start()),以代码和本文配置为准
continuous-insight-plan.md、tool-call-detail-plan.md 等 各特性设计稿(根目录 *-plan.md / *.md)
readme.md 离线栅格地图(pmtiles 转换)与 regInfo 授权工具的零散说明