前端接入与联调指南
核对接口、权限、状态能力、查询、分页和前端交互。
浏览全部手册
本页目录
文档来源与 Markdown 原文
权威正文:ineed-core/docs/project-development/frontend-integration-guide.md。网站按工作区快照同步,原文中的历史日期和验证范围保留。
开始编码前核对同版本源码;跨仓文件引用可在源码定位目录查找。
下载 Markdown 原文 ↓文档定位
本文档面向:
- 前端开发者
- 负责前后端联调的后端开发者
- 编写业务需求说明的人
重点回答三类问题:
- 前端在
ineed-core里真正应该依赖哪些稳定契约 webmvc与webflux两条线对前端来说哪些语义必须保持一致- 新业务模块在需求阶段,哪些前端信息必须先写清楚,避免后续返工
如果你要先理解当前框架模块边界,先读 module-capability-map.md。 如果你要新建业务模块,继续读 business-module-layout-guide.md。 如果你要写业务需求说明,继续读 module-requirements-template.md。 如果你要用代码生成器或自动化工具同时生成后端和前端,继续读 development-contract.md 和 code-style-guide.md。
前端只依赖这些稳定契约
前端不应直接围绕 entity、repository、数据栈实现做联调。
前端真正应该依赖的是:
AO作为创建、编辑、导入等提交对象Query作为业务筛选条件对象CommonParameters作为分页、搜索、排序等通用查询参数VO作为列表、详情、树、字典等展示对象ResponseResults<T>作为统一响应外壳QueryResults<T>作为分页结果对象
这套契约主要位于:
ineed-core-baseineed-core-webmvcineed-core-webflux
新业务模块面向前端的对象应位于后端 core 子模块的 contract/ao、contract/query、contract/vo、contract/dto 包下。需求、接口说明和前端联调文档统一称为 AO / Query / VO / DTO 契约对象,不再把这些对象写成 pojo。
当前前端实现主要通过以下入口消费这些契约:
ineed-frontend/src/shared/api/request.js统一注入 token,处理ResponseResults、HTTP 错误和登录过期。ineed-frontend/src/shared/api/serviceFactory.js通过createConfigCrudService(url, options)组合标准 CRUD / query / data status / recycle API。ineed-frontend/src/shared/store/storeFactory.js通过createConfigCrudStore(storeId, service, options)组合列表、编辑、详情、回收站和状态动作。ineed-frontend/src/shared/composables/support/dataStatusActionConfigs.js定义状态按钮、权限后缀、显示条件和确认文案。ineed-frontend/src/app/router/index.js使用路由meta.resourceKey或meta.resourceKeyBuilder做页面级权限判断。
新模块前端代码应优先复用这些工厂和约定,只有领域特有接口才在模块自己的 service/*.js 里额外补方法。
登录 Token 与在线会话
当前安全框架把 JWT 当作前后端传输凭证,服务端 Session 才是登录状态的权威来源。
前端接入时遵守:
- 登录接口返回的 token 只需要按统一 request 层注入到后续请求中,前端不要解析 token 内容来判断登录身份、租户或权限。
- JWT 只承载最小会话标识,例如
sid;不要依赖 JWT 里的过期时间、用户字段或权限字段驱动页面状态。 - token 是否仍有效由后端通过 Redis Session 校验兜底;前端收到统一未登录 / 会话失效错误后,按错误码进入重新登录或刷新当前登录态流程。
- 在线会话管理接口使用
/security/online-session语义,资源标识使用security.online-session;不要继续生成或消费旧的用户维度在线管理路径与资源标识。 - 在线会话列表面向
OnlineSessionVO,展示字段来自 VO;强制下线等动作以sid为目标会话标识,不要用用户名、用户 ID 或 token 全串作为操作主键。 - Redis 在线会话索引语义是
ONLINE_SESSION,前端、文档、测试样例不要继续引用旧的ONLINE命名。
AO / Query / VO 的前端语义
AO
AO 是前端提交给后端的应用对象,主要用于:
- 新增表单
- 编辑表单
- 批量导入
- 自定义业务动作入参
基础约束来自 AbstractAO:
- 统一带
id - 保存时
id必须为空 - 更新时
id不能为空
这意味着前端在新增和编辑时,不能把同一份未区分状态的表单对象直接复用成两套语义。
Query
Query 是业务筛选条件对象,只承载业务字段,不承担分页与排序。
例如:
- 名称
- 编码
- 类型
- 状态
- 时间区间
分页、搜索关键字、排序这些通用参数不应塞进业务 Query 里,而是继续通过 CommonParameters 传递。
VO
VO 是前端看到的展示对象,主要用于:
- 列表行
- 详情页
- 树节点
- 字典项
- 导出对象
基础约束来自 AbstractVO:
- 统一带
id
同一个业务对象在 webmvc 与 webflux 两条线中的 VO 字段语义应保持一致,不允许一边有字段、另一边缺字段。
通用查询参数怎么传
标准查询入口会把前端传入的 CommonParameters + Query 组装成 QueryParameters。
前端真正需要关注的是 CommonParameters:
dc防缓存动态参数searchKey通用关键字搜索current当前页码pageSize每页条数sortJson排序 JSON 字符串
sortJson 对应的排序对象字段为:
property排序属性。这里必须传后端实体属性名,例如createdTimestamp,不要传 SQL 片段、列别名表达式或id desc这类拼接内容。direction排序方向,支持asc、ASC、ascend、desc、DESC、descend
当前 JDBC / R2DBC / MyBatis-Flex 标准查询实现会按实体字段做排序白名单校验。非法或未知的 property 不应作为有效排序条件进入 SQL。
标准查询接口对前端更接近下面这种调用方式:
GET {controllerRoot}
?current=1
&pageSize=20
&searchKey=zhang
&sortJson=[{"property":"createdTimestamp","direction":"descend"}]
&name=张三
&enabled=true
其中:
current / pageSize / searchKey / sortJson来自CommonParametersname / enabled这类业务字段来自具体Query
除非某个自定义接口明确要求,否则前端不需要自己手工构造 QueryParameters JSON。
当前前端服务与 Store 落地方式
标准模块的前端服务通常长这样:
import request from '@/shared/api/request';
import { API_PREFIX } from '@/shared/config/constants';
import { createConfigCrudService } from '@/shared/api/serviceFactory';
const URL = 'business/customer';
export const customerDataStatusCapabilities = {
enable: true,
lock: false,
default: false,
primary: false,
publish: false,
reserve: false
};
export default {
...createConfigCrudService(URL, { dataStatusCapabilities: customerDataStatusCapabilities }),
findProfile(id) {
return request.get(`${API_PREFIX}/${URL}/${id}/profile`);
}
};
约定如下:
URL不带/api前缀,由createConfigCrudService内部拼接API_PREFIX。- 只有自定义接口需要直接引用
API_PREFIX。 dataStatusCapabilities必须来自需求或后端实体的DataStatusFeature开关,不能默认全开。- Store 优先使用
createConfigCrudStore(storeId, service, { tree, dataStatusCapabilities })。 - 如果模块是树结构,前端 service/store 要同时打开
tree: true并确认后端提供/tree查询能力。
字段和页面代码应围绕 AO / Query / VO 分开设计:
| 前端文件类型 | 对应后端契约 | 说明 |
|---|---|---|
service/*.js |
Controller 路径与标准后缀 | 只封装 API,不承载页面状态 |
store/*.js |
ResponseResults / QueryResults |
只处理加载、列表、编辑、详情、动作状态 |
routes.js |
resourceKey / 页面入口 |
路由 meta.resourceKey 必须能映射到后端权限点 |
pages/*.vue |
VO / Query / action 能力 | 组合表格、表单、状态动作和自定义页面行为 |
| schema / columns 文件 | AO / Query / VO 字段 | 维护表单字段、查询字段、列表列、详情字段、校验规则 |
如果一个模块没有 schema/columns 独立文件而是内联在页面中,新增字段时也必须按上表逐项核对,不要只改表单或只改列表。
统一返回外壳
无论是 webmvc 还是 webflux,对前端可见的统一响应模型都应保持同一语义:
traceId请求追踪号success是否成功errorCode业务错误码errorMessage错误消息alertMessage友好提示data业务数据
成功响应示例:
{
"traceId": "7a1c6f3a0f0d4e84",
"success": true,
"errorCode": null,
"errorMessage": null,
"alertMessage": "保存成功",
"data": {
"id": "1001",
"name": "示例对象"
}
}
分页响应示例:
{
"traceId": "7a1c6f3a0f0d4e84",
"success": true,
"data": {
"total": 52,
"first": 1,
"pageCount": 3,
"pageSize": 20,
"current": 1,
"list": [
{
"id": "1001",
"name": "示例对象"
}
]
}
}
前端联调时建议遵守:
- 先按 HTTP 状态码区分是否成功返回
- 再按
success做业务成功判断 - 任何异常反馈都保留
traceId,便于后端排查 alertMessage作为提示文案使用,不要把它当成错误码- 需要分支处理时优先依赖
errorCode,不要只匹配中文报错文案
分页对象语义
标准分页对象 QueryResults<T> 至少包含:
total总记录数first第一条序号pageCount总页数pageSize每页条数current当前页码list当前页数据
前端表格、分页器、导出预览应统一围绕这组字段消费,不要为不同数据栈分别写三套分页适配。
标准接口能力一览
控制器根路径由业务控制器自己的类级 @RequestMapping 决定。
下面列的是标准后缀语义,来源于 CoreConstant.Urls:
| 能力 | 方法 | 标准路径后缀 | 典型入参 | 典型返回 |
|---|---|---|---|---|
| 创建 | POST |
{root} |
AO |
ResponseResults<VO> |
| 批量创建 | POST |
{root}/batch |
Collection<AO> |
ResponseResults<Iterable<VO>> |
| 更新 | PUT |
{root} |
AO |
ResponseResults<VO> |
| 详情 | GET |
{root}/{id} |
id |
ResponseResults<VO> |
| 批量详情 | GET |
{root}/batch?idSet=... |
idSet |
ResponseResults<Iterable<VO>> |
| 条件查询 | GET |
{root} |
CommonParameters + Query |
ResponseResults<QueryResults<VO>> |
| 逻辑删除 | DELETE |
{root}/{id} |
id |
ResponseResults<Void> |
| 批量逻辑删除 | DELETE |
{root}?idSet=... |
idSet |
ResponseResults<Void> |
| 恢复 | PUT |
{root}/recovery/{id} |
id |
ResponseResults<Void> |
| 批量恢复 | PUT |
{root}/recovery |
Set<String> |
ResponseResults<Void> |
| 启用/禁用 | PUT |
{root}/enable/{id}、{root}/disable/{id} |
id |
ResponseResults<Void> |
| 锁定/解锁 | PUT |
{root}/lock/{id}、{root}/unlock/{id} |
id |
ResponseResults<Void> |
| 发布/撤销发布 | PUT |
{root}/publish/{id}、{root}/withdraw/{id} |
id |
ResponseResults<Void> |
| 默认/取消默认 | PUT |
{root}/default/{id}、{root}/non-default/{id} |
id |
ResponseResults<Void> |
| 主要/取消主要 | PUT |
{root}/primary/{id}、{root}/non-primary/{id} |
id |
ResponseResults<Void> |
| 账号能力 | PUT |
{root}/account/passwd/reset/{id} 等 |
id |
ResponseResults<Void> |
如果某个实体没有开启对应数据状态能力,前端不要默认假定这些按钮和接口一定存在。
注意:当前前端通用 data status helper 中,发布的反向动作使用了 non-publish 命名;而 CoreConstant.Urls 和 WebMvc/WebFlux IPublishController 使用的是 withdraw。在代码统一前,启用 publish 能力的模块必须显式确认前端调用路径与后端控制器一致,不能盲目依赖默认 helper。
URL 命名与迁移调整
业务 URL 应优先表达稳定资源层级,不要把多个资源语义压成一个横线单词。遇到历史 URL 调整时,先做全量扫描和影响面确认,再一次性对齐后端、前端、权限清单和测试。
统一命名规则:
- 前端页面路径使用业务层级,例如
/resource/number/serial/definition、/resource/number/serial/pool、/resource/number/serial/data。 - 后端管理 API 与页面层级保持同一资源语义,例如
/api/resource/number/serial/definition。 - 后端运行时 API 仍按运行时入口分组,例如
/api/runtime/resource/number/serial/{applicationKey}/{serialNumberKey}/preview。 createConfigCrudService(url, options)里的url不带/api,但必须和后端 Controller 根路径去掉API_PREFIX后一致。permissionUrl中,menu/page写前端访问路径,api写后端接口路径;两者都要随 URL 调整同步更新。resourceKey、模块目录、组件路径不因为 URL 层级调整而机械改名,除非需求明确要求一起重命名。
调整步骤:
- 先用全文搜索列出旧路径的所有出现位置,至少覆盖后端常量、Controller、权限清单、前端 routes/service/store/page、mock、E2E。
- 确定目标路径后,后端优先修改模块
Constant.Urls,避免 Controller 中散落字面量路径。 - 同步更新权限清单中的前端菜单 URL 和后端 API URL,确保授权后台看到的路径与真实入口一致。
- 同步更新前端
routes.js、模块service/*.js、运行时自定义接口和 Playwright 用例。 - 如果运行时接口的路径参数语义变化,例如从
ruleKey变为applicationKey + serialNumberKey,前端页面和 service 方法签名必须一起调整,不能只替换 URL 字符串。 - 对兼容 redirect 明确做产品决策:需要兼容时只保留列出的旧入口;要求“一刀切”时删除旧路由和旧 API,不留下临时 redirect。
- 修改后再次搜索旧 HTTP 路径,确认没有新增残留;保留的模块目录名、import 路径或
resourceKey需要能解释清楚。 - 在脏工作区中提交时,只暂存本次 URL 调整相关 diff。混有无关改动的文件必须用 selective staging 或
git apply --cached精确暂存,再用git diff --cached复核。
调整示例:
旧页面:/resource/serial-number-definition/manage
新页面:/resource/number/serial/definition
旧 API:/api/resource/serial-number/definition
新 API:/api/resource/number/serial/definition
旧运行时 API:/api/runtime/resource/serial-number/{ruleKey}/preview
新运行时 API:/api/runtime/resource/number/serial/{applicationKey}/{serialNumberKey}/preview
webmvc 与 webflux 对前端必须保持一致的点
新增功能默认应同时评估 webmvc 与 webflux 两条线。
对前端来说,必须保持一致的不是“是不是 Mono”,而是下面这些外部语义:
- 控制器根路径语义
- URL 后缀语义
resourceKey与按钮权限点AO / Query / VO字段集合ResponseResults外壳QueryResults分页字段- HTTP 状态码语义
errorCode与错误消息语义
前端不应因为后端采用 webflux 就另写一套接口字段解析逻辑。
对前端而言,Mono<ResponseResults<T>> 和 ResponseResults<T> 的区别属于服务端实现细节,不应演变成两套 JSON 契约。
按钮权限点与 resourceKey
IWebMvcApi 与 IWebFluxApi 都要求业务控制器提供 getResourceKey() 和 getResourceName()。
getResourceKey() 是稳定权限资源标识,getResourceName() 是业务展示名。OpenAPI 输出公共接口摘要时会用 getResourceName() 替换 资源 占位,例如 创建资源 输出为 创建系统身份。
业务控制器应优先从模块常量读取这两个值:XxxConstant.Resource.KEY_* / XxxConstant.Resource.NAME_*。
最终权限点通过:
resourceKey + "." + action
拼出来。
permissionKey 统一使用点号分隔,禁止使用 :。推荐格式为 {moduleKey}.{resource}.{action},例如 platform.area.create。
权限清单中需要同时区分目录、前端导航、后端接口和页面按钮:
catalog表达目录或分组,不对应具体前端组件或后端接口,也不配置permissionUrl/component。menu表达独立前端菜单入口,permissionUrl填前端访问路径,component填真实前端组件路径,icon只给可见菜单节点使用。page表达隐藏/从属页面,不独立出现在菜单中,例如详情、编辑、配置、主从资源子列表页;这类页面通常依赖主资源 ID,后端会出现ISearchOfMasterIdController/search-of-master-id能力。api的permissionUrl填后端接口路径,用于表达查询、详情、字典、回收站查询、search-of-master-id等接口能力。button只表达页面上的可见操作按钮,不填permissionUrl/component/icon。- 不要把多个独立菜单入口错误包在一个
menu下再生成为page。需要中间分组时使用catalog,例如安全中心 catalog -> 系统身份管理 catalog -> 系统身份 menu / 系统身份分组 menu。 orderWeight按权限树DESC规则设计,权重越大越靠前;推荐顺序是辅助查询 API、列表查询、CRUD、状态操作、回收站操作。permissionDescription面向后台授权人员阅读,必须写业务语义,不要把idSet、ID 集合、query、commonParameters等后端参数名写进说明。
常见 action 取值来自 CoreConstant.ResourceKey,例如:
createbatch-createupdatelogic-deletebatch-logic-deletefind-by-idbatch-find-by-idrecoveryenabledisablelockunlockpublishdefaultprimaryaccount-passwd-reset
因此需求说明里必须提前写清:
- 控制器根路径
resourceKey- 页面按钮和权限点映射
- 路由
meta.resourceKey或meta.resourceKeyBuilder
否则前端菜单、按钮显隐和后端授权很容易对不上。
当前前端权限判断还会做少量历史动作别名兼容:
save可以映射到createdetails可以映射到details或find-by-idrecycle可以映射到recoveryphysics-delete可以映射到physics-delete或logic-delete
这些别名只用于兼容前端权限判断,不应作为新后端权限命名的依据。新接口仍应优先使用 CoreConstant.ResourceKey 中的标准 action。
导入导出与 Excel 约定
AO / VO 不只是表单和展示对象,也要预留后续导入导出能力。
当前约定是:
- 需要导入的对象优先落在
AO - 需要导出的对象优先落在
VO - 只要业务已经明确存在导入导出场景,就应在
AO / VO上直接考虑@ExcelProperty - 即使当前阶段暂未接入 Excel,也要先把字段中文名、列含义、顺序、是否必填写进需求,避免后续返工
需求里至少要先写清:
- 哪些字段参与导入
- 哪些字段参与导出
- 列头中文名
- 是否需要模板下载
- 是否允许部分字段只导出不导入
写需求时前端信息至少补齐这些
参考 module-requirements-template.md,前端相关内容至少要补齐:
- 控制器根路径
resourceKey- 页面路由或页面入口
- 列表字段
- 查询字段
- 详情字段
- 创建字段
- 编辑字段
- 默认排序
- 按钮权限点
- 是否需要回收站
- 是否需要状态切换
- 是否需要账号能力
- 是否需要导入导出
- 导入导出列头与字段映射
- 是否要求
webmvc与webflux两条线都开放同等能力 - 前端模块路径,例如
ineed-frontend/src/modules/business/customer - service/store/page/route/schema 是否都需要新增或修改
- 是否复用
createConfigCrudService/createConfigCrudStore dataStatusCapabilities的明确取值- 路由名称、路由 path、菜单标题和页面级
resourceKey - 表格列、查询项、创建表单、编辑表单、详情面板是否字段一致
- 自定义接口的 URL、方法、入参、返回
data结构和错误码 - Playwright E2E 是否需要新增 fixture、登录凭据依赖和跳过条件
前端代码生成的最小输入
如果用代码生成器或自动化工具处理前端联调、页面字段整理任务,输入至少要提供:
后端 Controller 根路径:
后端 resourceKey:
前端模块目录:
路由 path/name/meta.resourceKey:
列表列:
查询字段:
创建 AO 字段:
编辑 AO 字段:
详情 VO 字段:
默认排序:
dataStatusCapabilities:
自定义接口:
需要新增或更新的 service/store/page/schema/routes:
需要新增或更新的 Playwright 用例:
实现前必须先核对后端 AO / Query / VO / Controller 与前端字段表是否一致;字段不一致时先报告缺口,不要自行猜字段。
联调检查清单
- 前端是否只依赖
AO / Query / VO / ResponseResults / QueryResults - 列表分页是否统一消费
current / pageSize / total / list - 查询接口是否通过
CommonParameters + Query传参,而不是自造分页对象 - 是否保留并展示
traceId - 是否按
errorCode做业务分支,而不是硬编码中文文案 - 页面按钮权限点是否与
resourceKey.action一致 - 页面路由、后端 API、权限清单、service URL 和 E2E 是否使用同一套资源路径
- URL 迁移后是否已搜索旧路径,且兼容 redirect 是否符合本次决策
- 如果有导入导出,
AO / VO字段和列头是否已经在需求里写清 - 如果本次功能是公共能力,
webmvc与webflux是否都已对齐
最后更新:2026-06-01
仍有疑问?按反馈清单整理复现信息 →