管理后台API迁移NestJS方案
首页 / 其他 / 文章

管理后台API迁移NestJS方案

当前管理后台(/admin-one 和 /admin 路由)的全部接口都在 one_enterprise_api(Java Spring Boot)中,但前端侧需要对这些接口进行更频繁的迭代和扩展。为避免前后端协作瓶颈,计划将管理后台...

管理后台 API 迁移至 NestJS 方案#

提出时间:2026-04-17
提出人:翔子(前端/Node)
审阅对象:后端 leader

一、背景#

当前管理后台(/admin-one/admin 路由)的全部接口都在 one_enterprise_api(Java Spring Boot)中,但前端侧需要对这些接口进行更频繁的迭代和扩展。为避免前后端协作瓶颈,计划将管理后台的核心 API 抽离为独立的 Node.js(NestJS)项目,逐步替代 Java 后端中的对应接口。

二、迁移范围#

先抽取 5 个路由组,共约 93 个 endpoint,涉及 16 个 Java Controller

路由前缀Java Controllerendpoint 数功能模块
/TeamTeamMemberController, TeamDepartmentController, CompanyJobController, CompanyPositionController, PersonalDepartmentController, TeamMemberQuitController, TeamOfficeController, UserGroupController, ExcelServiceController~57团队成员/部门/职位/岗位/离职/办公地点/用户组/Excel 导出
/teamTeamInfoController, WorkSpaceController~13企业信息/工作空间
/contactContactController, ContactPersonalController, ContactUserGroupController~19通讯录搜索/部门成员列表/规则配置/个人分组/用户组
/UserInviteApplyController2邀请申请
/subManagerAppSubManagerController2应用子管理员

未包含的模块:考勤、文档、知识库、会议、日程、电子签、统计日志等非核心管理接口,仍由 Java 端提供。

三、技术选型#

层级技术说明
框架NestJS + TypeScript与 Spring 类似的依赖注入架构,便于后端同学理解
ORMPrisma替代 MyBatis-Plus,类型安全的查询
数据库MySQL共用现有 lowcode 库,不迁移数据
缓存Redis复用现有 Redis 实例
鉴权复用现有 SSO gRPC 服务不调用 HTTP SSO 接口,直接 gRPC 调用

四、鉴权方案(关键决策)#

现有 Java 鉴权链路#

请求 → RemoveVersionFilter (剥离 /v1/admin-one/ 前缀)
→ AuthorizationInterceptor
→ SSO gRPC 调用 (127.0.0.1:9207, SsoService.Verify)
→ 返回 user_uuid + team_uuid
→ 查本地 ddm_team_member 表获取 roleType
→ 注入 CurrentUser

NestJS 复用方案#

直接复用同一个 SSO gRPC 服务,不走 HTTP SSO 接口:

请求 → NestJS Middleware (剥离版本号前缀,同 Java)
→ AuthGuard
→ gRPC 调用 SsoService.Verify(token)
→ 地址: 127.0.0.1:9207
→ Proto: proto/sso.proto
→ 入参: VerifyParam { token }
→ 出参: VerifyResponse { status, data: Token { user_uuid, team_uuid } }
→ status === 0 时,查本地 ddm_team_member 表获取 roleType
→ 注入 Request (userUuid, teamUuid, roleType)

Proto 定义sso.proto):

service SsoService {
rpc Verify(VerifyParam) returns (VerifyResponse);
}
message VerifyParam {
string token = 1;
}
message VerifyResponse {
int64 status = 1; // 0 成功,非 0 失败
string message = 2;
Token data = 3;
}
message Token {
string user_uuid = 1;
string team_uuid = 6;
}

Node 端使用 @grpc/grpc-js + @grpc/proto-loader 实现调用,与 Java 端的 @GrpcClient("sso-grpc-server") 效果一致。

优势

  • 不需要重写 SSO 鉴权逻辑
  • SSO 服务升级时两端自动同步
  • token 格式、过期策略、登出逻辑全部由 SSO 统一管理

白名单机制#

与 Java 端一致:

  • security.permiturls 配置的路径跳过鉴权
  • @PublicAccess() decorator 标记的接口跳过鉴权
  • @NoAdminVerification() 标记的接口跳过后台权限校验

五、涉及的数据表#

核心表(必须)#

表名用途
ddm_team_info企业信息
ddm_team_member团队成员(含 roleType、isBan、isUse 等)
ddm_team_department团队部门树
ddm_department_path部门层级关系(path 查询优化)
ddm_department_member部门成员关联
ddm_company_job职务
ddm_company_position岗位
ddm_personal_department个人创建的部门
ddm_user_group_type用户组类型
ddm_user_group用户组
ddm_user_group_member用户组成员
ddm_team_office办公地点
ddm_invite_apply邀请申请
ddm_app_sub_manager应用子管理员
ddm_contact_rule通讯录规则配置

辅助表(按需)#

表名用途
ddm_team_member_quit离职记录
ddm_workspace / ddm_space / ddm_space_member工作空间
ddm_team_domain团队域名配置
ddm_login_token登录 token(降级鉴权用)

六、现有 Java 服务中的外部依赖#

NestJS 项目需要处理以下依赖:

依赖来源NestJS 处理方式
SSO 验证gRPC (127.0.0.1:9207)✅ 复用,@grpc/grpc-js 调用
用户信息IUserInfoService(需确认数据源)❓ 待确认:是否来自 gRPC 或其他服务
Redis本地 Redis✅ 复用,ioredis 连接
MySQL本地 MySQL✅ 复用,Prisma 连接

待确认项

  1. IUserInfoService 数据来源:Java 代码中大量调用此服务获取用户姓名、手机、头像等信息。需要确认数据来自哪里(gRPC 服务 / 另一张数据库表 / 外部 API)。如果也在 MySQL 中,需要补充对应的 Prisma model。

  2. gRPC 调用范围:部分 endpoint 可能涉及其他 gRPC 服务(IM、日程、文档空间等)。需要确认本次 5 个路由组中哪些 endpoint 实际依赖了这些外部服务。

七、API 响应格式#

保持与 Java 端一致的 ResponseDTO 格式:

{
"status": 0,
"message": "ok",
"data": { ... }
}

列表接口统一包装:

{
"status": 0,
"message": "ok",
"data": { "list": [...] }
}

失败响应:

{
"status": 1,
"message": "错误信息",
"data": {},
"errDetail": { "uri": "...", "ip": "...", "qmpLogId": "..." }
}

八、URL 路由兼容#

前端现有请求格式:POST /v1/admin-one/Team/showTeamMember

NestJS 中间件处理(复刻 Java RemoveVersionFilter 逻辑):

/v1/admin-one/Team/showTeamMember → /Team/showTeamMember
/v1/admin-one/team/getTeamInfoBasic → /team/getTeamInfoBasic
/enterprise/admin-one/contact/xxx → /contact/xxx (带 enterprise 标记)

配置规则(同 Java application.base.yml):

^(/v\d+)?/(admin-one|app)/ → /
/enterprise/admin-one/ → / (并标记 enterprise=true)

前端无需改动 URL,只需将 API 网关/反向代理指向新的 NestJS 服务即可。

九、项目结构#

nestjs-admin/
├── prisma/
│ └── schema.prisma # 数据库 schema
├── proto/
│ └── sso.proto # SSO gRPC proto(从 Java 端拷贝)
├── src/
│ ├── main.ts # 入口,端口 12000
│ ├── app.module.ts
│ ├── common/
│ │ ├── guards/auth.guard.ts # SSO gRPC 鉴权
│ │ ├── filters/exception.filter.ts # 全局异常处理
│ │ ├── interceptors/response.interceptor.ts
│ │ ├── decorators/public-access.decorator.ts
│ │ └── middlewares/url-prefix.middleware.ts # URL 前缀剥离
│ ├── team/ # /Team + /team 路由组
│ ├── contact/ # /contact 路由组
│ ├── user/ # /User 路由组
│ └── sub-manager/ # /subManager 路由组
├── package.json
└── tsconfig.json

十、实施计划#

阶段内容预估
P1项目初始化、Prisma Schema、gRPC 连接配置、鉴权 Guard1-2 天
P2/subManager + /User(最简单,2+2 个 endpoint,验证链路)0.5 天
P3/team(企业信息,纯 DB 操作)1 天
P4/contact(通讯录,涉及多表关联查询)2-3 天
P5/Team(核心模块,57 个 endpoint,涉及外部服务调用最多)5-7 天
P6联调验证、对比 Java/Node 响应一致性、性能测试1-2 天

十一、风险与缓解#

风险影响缓解
IUserInfoService 数据源不明确无法实现涉及用户详情的接口优先确认,可能需要后端配合提供 gRPC 或 HTTP 接口
复杂 SQL 查询(如部门树 path 查询、子部门递归)Prisma 可能无法直接表达使用 $queryRaw 写原生 SQL,功能先行
并发写入导致的数据不一致(MySQL 共用)Node 和 Java 同时操作同一库后续迁移阶段注意事务隔离,当前阶段风险低
gRPC 服务不可用鉴权完全失效降级到 Redis 查 ddm_login_token

十二、需要的后端配合#

  1. 确认 IUserInfoService 的数据来源和查询方式(最关键)
  2. 确认本次 5 个路由组中是否有 endpoint 依赖了其他 gRPC 服务(IM、日程、文档等)
  3. 确认 SSO gRPC 服务地址(当前是 127.0.0.1:9207,生产环境可能不同)
  4. 协助 review 关键 SQL 查询(特别是部门树、权限相关的复杂查询)