前言

科研3.0系统前后端代码在一个工程里,代码仓库地址:https://gitlab.cmkn.cn/isrsp/researchplatform

新人开发入门:东篱智慧科研系统

适用对象:首次参与本项目的 Java / Vue 开发人员。命令是操作指南,不表示已在新机器完成启动验证。账号、租户配置及外部服务需要团队提供。

建议阅读顺序:本文 → AI 辅助开发实战教程 → 与任务相关的源码及专题文档。

1. 先理解这个系统

这是科研业务管理平台,覆盖人员、项目申报与立项、成果、经费、学科建设、科研诚信及审批流等业务。后端是一个 Spring Boot 应用装配多个 Gradle 模块,前端是 Vue 应用;这些模块不是分别启动的微服务。

项目的重要特点是“业务代码 + 配置共同决定行为”:

  • 表单:动态组件与表单配置共同决定字段、校验、联动和展示。
  • 列表:查询定义决定查询条件、返回列、SQL 和部分操作入口。
  • 流程:Camunda 流程定义、业务处理器和业务单据状态共同参与审批。
  • 租户:同一份代码在不同租户下可能加载不同的菜单、权限、表单和流程。

因此,“页面少一个字段”不一定需要新增 Vue 页面,“按钮看不到”不一定是前端 bug,“改了 BPMN”也不代表运行中的流程实例已经切换版本。

2. 第一周路线与交付物

阶段 要完成的事 完成标准
第一天 获取环境资料,导入工程,运行前端及后端或连接指定开发后端 能登录指定租户,说明请求实际发往哪里;记录未就绪的依赖
第二天 跟踪“关于”接口,再跟踪一个真实业务列表 能指出页面、模型、API、UseCase、数据来源及权限位置
第三天 阅读动态表单、查询定义和流程配置 能判断一个需求应该改代码、迁移还是租户配置包
第四天 在个人分支完成一个小需求并补充必要验证 提供最小差异、测试命令及实际结果
第五天 完成代码评审及测试环境验收 解释兼容性、权限、租户边界与未验证项目

入职时向导师获取:仓库及分支规范、JDK/Node 安装基线、依赖镜像访问方式、脱敏开发数据库、测试租户及各角色账号、租户配置包位置与版本、附件/文档转换等服务配置、提交和发布流程。仓库没有提供可直接依赖的统一 Docker Compose 新人环境;不要假定空数据库启动后就能完成所有业务操作。

3. 工程地图

路径 内容 / 从哪里看起
src/main/java/cn/net/keyan/research/Application.java 应用入口,开启调度、异步及流程应用
src/main/resources/application*.properties 公共和环境配置,使用前核实连接目标
modules/ 业务模块,按领域及职责拆分
frameworks/ Payload、Id、上下文、权限、持久化及测试等基础能力
frontends/research.webui/ Vue 前端,从 src/main.ts、src/router/index.ts 阅读
src/main/resources/db/migration/ Flyway SQL 迁移;Java 迁移另在 src/main/java/db/migration/
src/main/resources/workflow/ BPMN 资源;运行时定义还需结合数据库和部署逻辑确认
gradle/libs.versions.toml 后端依赖版本
gradle/config/scripts/、coverage.gradle 构建、Checkstyle、测试和覆盖率约束
scripts/ 检查、构建、发布及专项维护脚本,先读脚本再运行
docs/、documents/、CLAUDE.md 专题文档与编码约定;示例和源码不一致时以当前实现为准

常用业务模块:

前缀 主要职责
iam / personnel 账号、租户、权限 / 人员
basics 基础设置、字典等公共业务
declaring / pm 申报 / 项目管理
fm 经费管理,包含拨款、预算、报销;不要将缩写理解为文件管理
om / academic 科研成果 / 学术相关业务
orchestrating 表单部署、业务流程编排与 Camunda 适配
querying 配置化查询
dc / sri 学科建设 / 科研诚信
importing / exporting 导入 / 导出
notifying / openapi / dlsm 通知 / 开放接口 / 商城对接

并非每个领域都有完全相同的四层目录,具体依赖看该模块 build.gradle。Gradle 项目名来自 settings.gradle:业务模块如 :pm.domain,基础模块如 :frameworks.test.postgres,前端为 :frontends.research.webui。

4. 环境准备与启动

4.1 版本和工具

工具 仓库依据 / 建议
Java JDK 17,见 gradle.properties;IDE 的 Gradle JVM 也设为 17
Gradle 使用仓库 ./gradlew,Wrapper 固定 7.6.1
后端 Spring Boot 3.3.0、Camunda 7.21.0、Flyway 9.22.3,见版本目录;README 中旧版参考链接不是当前版本声明
Node 当前前端没有声明 engines 或统一 Node 版本;使用团队验证的版本,不根据 @types/node 推断运行版本
Yarn 前端 packageManager 指向 Yarn 1.22.22;优先保持现有 Yarn 工作流,不混用包管理器更新锁文件
数据库 PostgreSQL;集成测试容器固定 postgres:15,实际开发库版本向团队确认
Docker 运行 Testcontainers 集成测试需要可用 Docker daemon 和镜像下载能力

在仓库根目录检查:

git status --short
java -version
./gradlew --version
node --version
yarn --version
docker info

首次 Wrapper、Gradle 依赖、前端依赖和容器镜像下载都需要网络。导入 IDE 时选择仓库根目录,等待 Gradle 同步;不要把单个业务模块当成独立工程。

4.2 后端:先准备连接,再启动

application.properties 和各 profile 文件包含数据库及外部服务配置。local 这个名字不保证所有依赖都在本机。请让导师提供独立开发环境配置,存于仓库外,不复制真实密码、私钥到文档或 AI 对话。

外置文件至少核实以下配置,按实际业务补齐附件、文档转换、SSO 等项:

# 示例占位,不能原样连接;使用团队提供的独立开发库
spring.datasource.url=jdbc:postgresql://<开发数据库主机>:5432/<数据库名>
spring.datasource.username=<开发数据库用户名>
spring.datasource.password=<开发数据库密码>
server.port=8081

外置配置会与仓库配置合并,不会自动清空其他已配置的外部服务。应用启用了调度和异步,启动前请确认使用的是隔离开发资源。Flyway 迁移也可能随启动执行,因此先确认目标库和初始化方案,不用共享生产库做入门练习。

在根目录运行,替换外置配置的绝对路径:

./gradlew bootRun --args='--spring.profiles.active=local --spring.config.additional-location=file:/绝对路径/researchplatform-dev.properties'

IDE 也可运行 cn.net.keyan.research.Application,传入相同的程序参数,工作目录设为仓库根目录。IDE 启动与 Gradle 资源生成行为可能不同;产品版本信息由根 build.gradle 的 generateVersionProperties 生成,不手动提交生成文件。

启动检查:日志出现应用启动完成、监听预期端口、数据库迁移无异常。默认关闭了 Actuator 端点,不要把 /actuator/health 返回 404 当作应用启动失败。账号、租户、授权、表单和流程初始化由导师提供;本文不约定默认管理员密码。

4.3 前端:明确选择联调目标

在前端目录安装依赖:

cd frontends/research.webui
yarn install --frozen-lockfile

若提示锁文件与依赖不一致,先核对所在分支和团队基线,不直接删锁文件或批量升级。

当前 vite.config.ts 的 /api 代理指向 QA,且没有启用路径重写。选择一种模式:

模式 配置方式
前端连接团队开发/QA 后端 核实 server.proxy['/api'].target 与测试租户;使用远端网关约定的路径
前后端均在本机 target 改成 http://localhost:8081;按下方配置移除 /api 前缀

本机后端 Controller 路径通常不含 /api,例如 /about。直接代理到本机应用时使用:

'/api': {
  target: 'http://localhost:8081',
  changeOrigin: true,
  rewrite: (path) => path.replace(/^\/api/, ''),
},

另一个重要检查点:Vite 注册了 mockServer(),它从 mock/ 读取配置并拦截匹配请求。做真实联调时,在个人工作区临时移除 plugins 中的 mockServer() 调用,并重启 Vite;不要只看到返回 200 就以为访问了后端。临时代理/Mock 调整不混入业务提交,恢复时保留自己和其他人的既有改动。

yarn dev

访问终端打印的地址。配置启用了自动打开浏览器,端口以实际输出为准。登录后通过浏览器 Network 和后端日志确认:请求到达预期服务,登录使用的是指定租户,数据来自真实接口。

5. 如何读懂一条业务链路

5.1 从“关于”功能开始

按以下顺序阅读,路径均相对仓库根目录:

  1. frontends/research.webui/src/components/header/MainHeader.vue:展示字段。
  2. 同目录 MainHeaderModel.ts、AboutInfo.ts:交互、加载与响应解析。
  3. frontends/research.webui/src/boot/axios.ts:/api 前缀、Bearer token、错误处理;成功响应直接返回 response.data。
  4. modules/basics.gateways/src/main/java/cn/net/keyan/research/basics/gateways/ohs/AboutController.java:GET /about。
  5. modules/basics.application/src/main/java/cn/net/keyan/research/basics/application/GetAboutInfoUseCase.java:权限声明、当前租户、版本及授权信息组装。
  6. 同目录 AboutInfo.java,以及 modules/basics.application/src/test/java/cn/net/keyan/research/basics/application/ 下同名测试:输出和边界行为。

这个例子也说明:不要机械照抄历史文档中的签名,当前前端 AboutInfo.load() 是实例方法,当前后端 AboutInfo 位于 application 模块。

Created with Raphaël 2.2.0
实现适配
Vue 页面
Model / RestApi
统一 axios
Vite 或部署代理
Controller / gateways
UseCase / application
业务对象与仓储接口 / domain
JPA 或外部服务 / gateways

图表示常见调用协作,不表示 domain 可以反向导入 gateways。业务规则应放到合适的业务对象中,Controller 保持轻薄,application 协调用例,gateways 实现存储及外部系统适配。

5.2 再读动态表单、查询和流程

场景 起点 必须继续追踪
动态表单 src/pages/customer-form/(前端) src/components/input/BaseInputModel.ts、src/components/dynamic-components.ts、表单部署配置及后端保存结构
配置列表 modules/querying.gateways/.../ohs/QueriesController.java POST /queries/{id}/executions → ExecuteQueryUseCase → 查询工厂/执行器 → 目标租户查询定义
审批流程 modules/orchestrating.* 表单、流程定义、任务处理器、业务单据及历史记录;涉及操作时检查 WorkflowBusinessDataGuard
数据字段 对应领域对象与 gateways 持久化实现 数据库列还是 JSON 内容、迁移、列表查询、导入导出及历史空值

这里的 ... 表示 Java 包路径,可按类名搜索,不是可复制的文件路径。优先用下面命令定位:

rg -n 'GetAboutInfoUseCase|class AboutInfo' modules frontends/research.webui/src
rg -n '目标字段名或接口片段' modules frontends/research.webui/src src/main/resources/db/migration
rg --files modules | rg 'QueryProcessSchedule|WorkflowBusinessDataGuard|QueriesController'

代码中找不到某租户的字段或查询时,先查配置归属。部分配置由独立租户配置包维护,应让导师确认仓库和发布方式;不要凭当前代码推定线上数据库内容。

6. 日常开发必须保留的约定

  • 后端复用 Id、Payload、ObjectSink / ValueSinkFactory、@UseCase 等框架能力;先找邻近实现和测试。
  • 前端通过 boot/axios 的 api 调接口,按实际返回结构解析。它已经解包成功响应,避免再习惯性读取一层 .data。
  • 默认从 GlobalUserContext 获取当前用户和租户;跨租户和匿名入口按现有业务约定与授权检查处理,不能简单信任客户端 tenantId。
  • 保持字段 key、绑定、默认值、顺序和历史空值兼容。金额规则与业务单据状态变化需追踪完整调用链。
  • 前端按钮可见性不等于后端操作权限;两侧都要核对。
  • SQL 迁移按 VYYYYMMDDHHMM__description.sql 命名,版本精确到分钟并检查是否冲突。不修改已执行迁移来“修复”旧库,新增迁移并说明目标租户、影响范围与回退方案。
  • 科研模块列表人员姓名从 personnel_persons 获取;使用 process-schedule-selector 时同步核对 QueryProcessSchedule#tableName() 映射。
  • 新增列表查询定义优先拆分到 query_definition_conditions、query_definition_fields、query_definition_parameters;字典选项优先复用 dict + meta.type。完整要求见 科研模块开发约束。
  • 流程变更要分别验证新实例和历史实例,不能只修改流程图;重启、撤回、资金退还等操作需要检查已有业务处理器。

7. 开发验证与提交

先运行受影响范围的检查,再在推送前完成仓库质量门禁。以下命令在根目录执行:

# 实际存在的测试类示例,任务名包含模块
./gradlew :basics.application:test --tests 'cn.net.keyan.research.basics.application.AboutInfoTest'

# 模块检查示例
./gradlew :basics.application:checkstyleMain :basics.application:checkstyleTest

# 仓库质量门禁(含 clean,耗时可能较长)
./scripts/check-all
# 资源充足时可改用 ./scripts/check-all-parallel

前端命令在 frontends/research.webui 执行:

# 单次运行;yarn test 默认进入监听模式
yarn test --run src/components/header/MenuTree.test.ts
yarn lint
yarn build
yarn coverage

后端 JaCoCo 根门禁对纳入统计的包要求指令、行、类、分支覆盖率均为 100%,排除项见 coverage.gradle。一个测试类通过不等于全模块或根门禁通过;不以增加排除项代替必要测试。只读取旧报告或用 -x test 复用旧执行数据,也不能证明本次修改通过了完整门禁。

报告常见位置:<模块>/build/reports/tests/test/、build/reports/allTests/、build/reports/jacoco/jacocoRootReport/。前端构建输出在 frontends/research.webui/dist/;后端打包可用 ./gradlew bootJar,产物位于 build/libs/。

scripts/build-all 不只是编译:还会清理用户主目录下匹配的旧 JAR/ZIP 并复制产物。新人本地验证优先使用上述检查和打包命令。package-all、push-all、deploy-* 属于交付流程,执行前按团队发布安排确认目标;CI 实际任务以 .gitlab-ci.yml 为准。

提交前:

  1. git diff --check、git diff --stat,确认没有临时代理、账号配置、无关格式化或锁文件变更。
  2. 只暂存本次任务文件,保留工作区已有改动。
  3. 使用仓库约定提交信息,例如 [docs]: 补充新人开发教程。
  4. 在评审说明里写清需求、改动、实际检查结果、是否需要迁移/配置部署及未验证项。

8. 常见问题排查表

现象 优先核对
Gradle 同步/下载失败 JDK 17、Wrapper 下载、依赖镜像网络、代理;不要先改依赖版本
前端有数据但本地后端没日志 Mock 是否命中、代理是否仍指向 QA
本机接口 404 浏览器 /api/about 是否被重写成后端 /about,后端端口是否一致
登录成功但没菜单/按钮 当前租户、账号角色、菜单和权限配置;不要直接放开鉴权
表单不随源码修改变化 实际表单部署、配置版本、组件注册和缓存;确认改的是当前租户使用的配置
流程图改了但实例没变化 实例使用的流程定义版本、部署记录、重启策略及历史数据
Testcontainers 失败 docker info、postgres:15 拉取、Docker 连接和容器日志
页面能打开但附件/报表失败 SFTP、转换服务、实际请求状态及服务日志;页面启动不等于所有依赖就绪
Flyway 校验或执行失败 首个异常、迁移版本/校验和、目标库基线;不直接执行 repair 或清空历史表
构建/测试全量失败 记录具体模块和首个失败;区分本次引入、既有失败、环境未就绪

验收记录要分开写:源码检查、单元测试、构建、浏览器操作、数据库迁移、外部服务联调。完成前几项不代表后几项也已验证。

9. 后续资料

作者:向海林  创建时间:2023-10-20 15:52
最后编辑:向海林  更新时间:2026-10-22 08:56