# CAD 模型与标注接口文档 面向前端联调使用,覆盖 `CadModelController` 与 `CadAnnotationController` 暴露的接口。 ## 1. 通用约定 ### 1.1 基础信息 | 项 | 说明 | | --- | --- | | 默认服务地址 | `http://localhost:8891` | | 接口前缀 | `/api/cad-models` | | 请求/响应格式 | `application/json` | | 时间格式 | `yyyy-MM-dd HH:mm:ss`,时区 `Asia/Shanghai` | | 字段命名 | JSON 使用小驼峰,如 `modelName` | | 空字段 | 后端全局配置为 `non_null`,响应中的 `null` 字段默认不返回 | ### 1.2 统一响应结构 成功响应: ```json { "code": "OK", "message": "success", "data": {}, "requestId": "b3f8..." } ``` 失败响应: ```json { "code": "INVALID_REQUEST", "message": "page 必须大于等于 1", "requestId": "b3f8..." } ``` ### 1.3 常见状态码与错误码 | HTTP 状态码 | code | 说明 | | --- | --- | --- | | 200 | `OK` | 请求成功 | | 404 | `NOT_FOUND` | 模型、建模历史、结构、功能或请求路径不存在 | | 409 | `CAD_MODEL_DUPLICATE` | 修改模型时,同分类下源 SolidWorks 文件名已存在 | | 422 | `INVALID_REQUEST` | 参数校验失败、请求体不合法、方法/媒体类型不支持 | | 500 | `INTERNAL_ERROR` | 系统异常或数据库异常 | ### 1.4 分页响应结构 ```json { "items": [], "page": 1, "size": 10, "total": 0 } ``` | 字段 | 类型 | 说明 | | --- | --- | --- | | `items` | array | 当前页数据 | | `page` | number | 当前页码,从 1 开始 | | `size` | number | 每页条数 | | `total` | number | 总记录数 | ## 2. 模型接口 ### 2.1 分页查询 CAD 模型列表 `GET /api/cad-models` 按创建时间倒序、ID 倒序返回模型列表。 #### Query 参数 | 参数 | 类型 | 必填 | 默认值 | 约束 | 说明 | | --- | --- | --- | --- | --- | --- | | `page` | number | 否 | `1` | `>= 1` | 页码 | | `size` | number | 否 | `10` | `1-100` | 每页条数 | | `categoryId` | number | 否 | - | 正整数 | 分类 ID | | `convertStatus` | string | 否 | - | `pending` / `success` / `failed` / `partial_failed` | 转换状态 | | `keyword` | string | 否 | - | - | 关键字,匹配 `modelName` 或 `sourceSwFilename` | #### 响应 data `PageResponse` ```json { "code": "OK", "message": "success", "data": { "items": [ { "id": 1, "categoryId": 10, "modelName": "支架模型", "sourceSwFilename": "bracket.SLDPRT", "sourceSwPath": "uploads/bracket.SLDPRT", "featureTreeJsonPath": "uploads/bracket-feature-tree.json", "viewPath": "uploads/bracket.glb", "applicationScenario": "机械装配", "material": "铝合金", "manufacturingMethod": "CNC", "unit": "mm", "userRequirement": "减重并保证强度", "designDescription": "含多个孔位和倒角", "convertStatus": "success", "createdAt": "2026-07-08 16:20:00", "updatedAt": "2026-07-08 16:20:00" } ], "page": 1, "size": 10, "total": 1 }, "requestId": "b3f8..." } ``` ### 2.2 查询 CAD 模型详情 `GET /api/cad-models/{id}` #### Path 参数 | 参数 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `id` | number | 是 | 正整数 | 模型 ID | #### 响应 data `CadModel` ### 2.3 修改 CAD 模型基础信息 `POST /api/cad-models/{id}` 支持部分字段更新。请求体可为空;为空或所有字段均未传时不更新,直接返回当前模型详情。 #### Path 参数 | 参数 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `id` | number | 是 | 正整数 | 模型 ID | #### 请求体 | 字段 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `categoryId` | number | 否 | 正整数 | 分类 ID | | `modelName` | string | 否 | 最大 255 字符 | 模型名称 | | `sourceSwFilename` | string | 否 | 最大 255 字符 | 源 SolidWorks 文件名 | | `sourceSwPath` | string | 否 | 最大 1024 字符 | 源文件路径 | | `featureTreeJsonPath` | string | 否 | 最大 1024 字符 | 特征树 JSON 路径 | | `viewPath` | string | 否 | 最大 1024 字符 | 预览文件路径 | | `applicationScenario` | string | 否 | 最大 255 字符 | 应用场景 | | `material` | string | 否 | 最大 255 字符 | 材料 | | `manufacturingMethod` | string | 否 | 最大 255 字符 | 制造方式 | | `unit` | string | 否 | 最大 64 字符 | 单位 | | `userRequirement` | string | 否 | - | 用户需求 | | `designDescription` | string | 否 | - | 设计说明 | | `convertStatus` | string | 否 | `pending` / `success` / `failed` / `partial_failed`,最大 32 字符 | 转换状态 | | `errorMessage` | string | 否 | - | 转换错误信息 | 同一 `categoryId` 下 `sourceSwFilename` 不能重复;当更新 `categoryId` 或 `sourceSwFilename` 时会触发唯一性校验。 #### 请求示例 ```json { "modelName": "支架模型 V2", "material": "6061 铝合金", "unit": "mm" } ``` #### 响应 data `CadModel` ### 2.4 查询模型建模历史列表 `GET /api/cad-models/{modelId}/histories` 按 `historyIndex` 升序、ID 升序返回。 #### Path 参数 | 参数 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `modelId` | number | 是 | 正整数 | 模型 ID | #### 响应 data `CadModelHistory[]` ```json { "code": "OK", "message": "success", "data": [ { "id": 101, "modelId": 1, "sourceFeatureId": "Feat-Extrude1", "historyIndex": 0, "historyName": "拉伸", "operationType": "Extrude", "stepPath": "uploads/history/101.step", "glbPath": "uploads/history/101.glb", "topologyPath": "uploads/history/101.topology.json", "convertStatus": "success", "createdAt": "2026-07-08 16:20:00", "updatedAt": "2026-07-08 16:20:00" } ], "requestId": "b3f8..." } ``` ## 3. 建模历史标注接口 ### 3.1 保存建模历史步骤标注 `POST /api/cad-models/{modelId}/histories/{historyId}/annotation` 同一个建模历史只能有一条标注。重复保存时按 `historyId` 覆盖原有标注内容。请求体可为空;为空时三个文本字段均按 `null` 保存或覆盖。 #### Path 参数 | 参数 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `modelId` | number | 是 | 正整数 | 模型 ID | | `historyId` | number | 是 | 正整数 | 建模历史 ID,必须归属当前模型 | #### 请求体 | 字段 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `modelingDescription` | string | 否 | - | 建模描述 | | `supplementDescription` | string | 否 | - | 补充描述 | | `remark` | string | 否 | - | 备注 | #### 请求示例 ```json { "modelingDescription": "通过草图轮廓进行基体拉伸", "supplementDescription": "该步骤决定主体厚度", "remark": "前端可作为历史步骤说明展示" } ``` #### 响应 data `CadModelHistoryAnnotation` ```json { "id": 201, "modelId": 1, "historyId": 101, "modelingDescription": "通过草图轮廓进行基体拉伸", "supplementDescription": "该步骤决定主体厚度", "remark": "前端可作为历史步骤说明展示", "createdAt": "2026-07-08 16:20:00", "updatedAt": "2026-07-08 16:20:00" } ``` ## 4. 结构接口 ### 4.1 创建 CAD 结构 `POST /api/cad-models/{modelId}/structures` 创建结构时必须选择至少一个建模历史步骤。结构与历史的关系按 `historyIds` 请求数组顺序保存,`sortOrder` 从 `0` 开始。 #### Path 参数 | 参数 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `modelId` | number | 是 | 正整数 | 模型 ID | #### 请求体 | 字段 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `structureName` | string | 是 | 非空,最大 255 字符 | 结构名称 | | `structureType` | string | 否 | 最大 64 字符 | 结构类型,未传时保存为空字符串 | | `purpose` | string | 否 | 最大 1024 字符 | 结构用途,未传时保存为空字符串 | | `solution` | string | 否 | 最大 1024 字符 | 结构方案,未传时保存为空字符串 | | `reason` | string | 否 | - | 结构原因 | | `remark` | string | 否 | - | 备注 | | `historyIds` | number[] | 是 | 非空、元素为正整数、不能重复、必须都归属当前模型 | 关联建模历史 ID 列表 | #### 请求示例 ```json { "structureName": "主体支撑结构", "structureType": "支撑件", "purpose": "承载上方组件并定位", "solution": "基体拉伸后增加加强筋", "reason": "提升抗弯能力", "remark": "与历史步骤 101、102 关联", "historyIds": [101, 102] } ``` #### 响应 data `CadStructure` ### 4.2 修改 CAD 结构 `POST /api/cad-models/{modelId}/structures/{structureId}` 普通字段支持部分更新,请求未传字段保持原值。请求体可为空;为空时不更新,返回当前结构详情。传入 `historyIds` 时,会按最终数组全量替换结构下的建模历史关系。 #### Path 参数 | 参数 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `modelId` | number | 是 | 正整数 | 模型 ID | | `structureId` | number | 是 | 正整数 | 结构 ID,必须归属当前模型且未逻辑删除 | #### 请求体 | 字段 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `structureName` | string | 否 | 非空,最大 255 字符 | 结构名称 | | `structureType` | string | 否 | 最大 64 字符 | 结构类型 | | `purpose` | string | 否 | 最大 1024 字符 | 结构用途 | | `solution` | string | 否 | 最大 1024 字符 | 结构方案 | | `reason` | string | 否 | - | 结构原因 | | `remark` | string | 否 | - | 备注 | | `historyIds` | number[] | 否 | 非空、元素为正整数、不能重复、必须都归属当前模型 | 传入时全量替换关系;不传时关系不变 | #### 请求示例 ```json { "purpose": "承载上方组件并提供装配定位", "historyIds": [101, 103, 104] } ``` #### 响应 data `CadStructure` ### 4.3 查询模型下结构列表 `GET /api/cad-models/{modelId}/structures` 只返回未逻辑删除的结构,按结构 ID 升序返回,并携带已关联的建模历史步骤。 #### Path 参数 | 参数 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `modelId` | number | 是 | 正整数 | 模型 ID | #### 响应 data `CadStructure[]` ### 4.4 查询结构详情 `GET /api/cad-models/{modelId}/structures/{structureId}` 用于结构编辑回显,返回结构基础信息和已关联的建模历史步骤。 #### Path 参数 | 参数 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `modelId` | number | 是 | 正整数 | 模型 ID | | `structureId` | number | 是 | 正整数 | 结构 ID,必须归属当前模型且未逻辑删除 | #### 响应 data `CadStructure` ### 4.5 删除 CAD 结构 `DELETE /api/cad-models/{modelId}/structures/{structureId}` 按模型归属校验后逻辑删除结构。删除后该结构不会再出现在结构列表和结构详情中;后端会同步清理该结构关联的建模历史关系,以及功能中引用该结构的关系。 #### Path 参数 | 参数 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `modelId` | number | 是 | 正整数 | 模型 ID | | `structureId` | number | 是 | 正整数 | 结构 ID,必须归属当前模型且未逻辑删除 | #### 请求体 无。 #### 响应 data 无。由于响应字段全局忽略 `null`,成功时通常不返回 `data` 字段。 ```json { "code": "OK", "message": "success", "requestId": "b3f8..." } ``` #### 失败说明 | HTTP 状态码 | code | 场景 | | --- | --- | --- | | 404 | `NOT_FOUND` | 模型不存在,或结构不存在、已删除、不是当前模型下的结构 | | 422 | `INVALID_REQUEST` | `modelId` 或 `structureId` 不是正整数 | ### 4.6 CadStructure 响应字段 ```json { "id": 301, "modelId": 1, "structureName": "主体支撑结构", "structureType": "支撑件", "purpose": "承载上方组件并定位", "solution": "基体拉伸后增加加强筋", "reason": "提升抗弯能力", "remark": "与历史步骤 101、102 关联", "historyItems": [ { "relationId": 401, "historyId": 101, "historyIndex": 0, "historyName": "拉伸", "operationType": "Extrude", "sortOrder": 0 } ], "createdAt": "2026-07-08 16:20:00", "updatedAt": "2026-07-08 16:20:00" } ``` | 字段 | 类型 | 说明 | | --- | --- | --- | | `id` | number | 结构 ID | | `modelId` | number | 模型 ID | | `structureName` | string | 结构名称 | | `structureType` | string | 结构类型 | | `purpose` | string | 结构用途 | | `solution` | string | 结构方案 | | `reason` | string | 结构原因 | | `remark` | string | 备注 | | `historyItems` | array | 关联建模历史步骤,按 `sortOrder` 升序 | | `createdAt` | string | 创建时间 | | `updatedAt` | string | 更新时间 | `historyItems` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | | `relationId` | number | 结构-历史关系 ID | | `historyId` | number | 建模历史 ID | | `historyIndex` | number | 建模历史顺序号 | | `historyName` | string | 建模历史名称 | | `operationType` | string | 操作类型 | | `sortOrder` | number | 关系排序,按请求数组顺序生成 | ## 5. 功能接口 ### 5.1 创建 CAD 功能 `POST /api/cad-models/{modelId}/functions` 创建功能时必须选择至少一个结构。功能与结构的关系按 `structureIds` 请求数组顺序保存,`sortOrder` 从 `0` 开始。 #### Path 参数 | 参数 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `modelId` | number | 是 | 正整数 | 模型 ID | #### 请求体 | 字段 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `functionName` | string | 是 | 非空,最大 255 字符 | 功能名称 | | `functionType` | string | 否 | 最大 64 字符 | 功能类型,未传时保存为空字符串 | | `goalDescription` | string | 否 | - | 功能目标描述 | | `remark` | string | 否 | - | 备注 | | `structureIds` | number[] | 是 | 非空、元素为正整数、不能重复、必须都归属当前模型且未逻辑删除 | 关联结构 ID 列表 | #### 请求示例 ```json { "functionName": "承载与定位", "functionType": "机械功能", "goalDescription": "支撑外部载荷并限制装配自由度", "remark": "由主体支撑结构和定位孔结构共同实现", "structureIds": [301, 302] } ``` #### 响应 data `CadFunction` ### 5.2 修改 CAD 功能 `POST /api/cad-models/{modelId}/functions/{functionId}` 普通字段支持部分更新,请求未传字段保持原值。请求体可为空;为空时不更新,返回当前功能详情。传入 `structureIds` 时,会按最终数组全量替换功能下的结构关系。 #### Path 参数 | 参数 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `modelId` | number | 是 | 正整数 | 模型 ID | | `functionId` | number | 是 | 正整数 | 功能 ID,必须归属当前模型且未逻辑删除 | #### 请求体 | 字段 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `functionName` | string | 否 | 非空,最大 255 字符 | 功能名称 | | `functionType` | string | 否 | 最大 64 字符 | 功能类型 | | `goalDescription` | string | 否 | - | 功能目标描述 | | `remark` | string | 否 | - | 备注 | | `structureIds` | number[] | 否 | 非空、元素为正整数、不能重复、必须都归属当前模型且未逻辑删除 | 传入时全量替换关系;不传时关系不变 | #### 请求示例 ```json { "goalDescription": "支撑外部载荷、定位并辅助装配", "structureIds": [302, 301] } ``` #### 响应 data `CadFunction` ### 5.3 查询模型下功能列表 `GET /api/cad-models/{modelId}/functions` 只返回未逻辑删除的功能,按功能 ID 升序返回,并携带已关联的结构。 #### Path 参数 | 参数 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `modelId` | number | 是 | 正整数 | 模型 ID | #### 响应 data `CadFunction[]` ### 5.4 查询功能详情 `GET /api/cad-models/{modelId}/functions/{functionId}` 用于功能编辑回显,返回功能基础信息和已关联的结构。 #### Path 参数 | 参数 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `modelId` | number | 是 | 正整数 | 模型 ID | | `functionId` | number | 是 | 正整数 | 功能 ID,必须归属当前模型且未逻辑删除 | #### 响应 data `CadFunction` ### 5.5 删除 CAD 功能 `DELETE /api/cad-models/{modelId}/functions/{functionId}` 按模型归属校验后逻辑删除功能。删除后该功能不会再出现在功能列表和功能详情中;后端会同步清理该功能下的结构关系。 #### Path 参数 | 参数 | 类型 | 必填 | 约束 | 说明 | | --- | --- | --- | --- | --- | | `modelId` | number | 是 | 正整数 | 模型 ID | | `functionId` | number | 是 | 正整数 | 功能 ID,必须归属当前模型且未逻辑删除 | #### 请求体 无。 #### 响应 data 无。由于响应字段全局忽略 `null`,成功时通常不返回 `data` 字段。 ```json { "code": "OK", "message": "success", "requestId": "b3f8..." } ``` #### 失败说明 | HTTP 状态码 | code | 场景 | | --- | --- | --- | | 404 | `NOT_FOUND` | 模型不存在,或功能不存在、已删除、不是当前模型下的功能 | | 422 | `INVALID_REQUEST` | `modelId` 或 `functionId` 不是正整数 | ### 5.6 CadFunction 响应字段 ```json { "id": 501, "modelId": 1, "functionName": "承载与定位", "functionType": "机械功能", "goalDescription": "支撑外部载荷并限制装配自由度", "remark": "由主体支撑结构和定位孔结构共同实现", "structureItems": [ { "relationId": 601, "structureId": 301, "structureName": "主体支撑结构", "structureType": "支撑件", "sortOrder": 0 } ], "createdAt": "2026-07-08 16:20:00", "updatedAt": "2026-07-08 16:20:00" } ``` | 字段 | 类型 | 说明 | | --- | --- | --- | | `id` | number | 功能 ID | | `modelId` | number | 模型 ID | | `functionName` | string | 功能名称 | | `functionType` | string | 功能类型 | | `goalDescription` | string | 功能目标描述 | | `remark` | string | 备注 | | `structureItems` | array | 关联结构,按 `sortOrder` 升序 | | `createdAt` | string | 创建时间 | | `updatedAt` | string | 更新时间 | `structureItems` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | | `relationId` | number | 功能-结构关系 ID | | `structureId` | number | 结构 ID | | `structureName` | string | 结构名称 | | `structureType` | string | 结构类型 | | `sortOrder` | number | 关系排序,按请求数组顺序生成 | ## 6. 公共数据结构 ### 6.1 CadModel | 字段 | 类型 | 说明 | | --- | --- | --- | | `id` | number | 模型 ID | | `categoryId` | number | 分类 ID | | `modelName` | string | 模型名称 | | `sourceSwFilename` | string | 源 SolidWorks 文件名 | | `sourceSwPath` | string | 源文件路径 | | `featureTreeJsonPath` | string | 特征树 JSON 路径 | | `viewPath` | string | 预览文件路径 | | `applicationScenario` | string | 应用场景 | | `material` | string | 材料 | | `manufacturingMethod` | string | 制造方式 | | `unit` | string | 单位 | | `userRequirement` | string | 用户需求 | | `designDescription` | string | 设计说明 | | `convertStatus` | string | 转换状态:`pending` / `success` / `failed` / `partial_failed` | | `errorMessage` | string | 转换错误信息 | | `createdAt` | string | 创建时间 | | `updatedAt` | string | 更新时间 | ### 6.2 CadModelHistory | 字段 | 类型 | 说明 | | --- | --- | --- | | `id` | number | 建模历史 ID | | `modelId` | number | 模型 ID | | `sourceFeatureId` | string | 源特征 ID | | `historyIndex` | number | 历史步骤顺序号 | | `historyName` | string | 历史步骤名称 | | `operationType` | string | 操作类型 | | `stepPath` | string | STEP 文件路径 | | `glbPath` | string | GLB 文件路径 | | `topologyPath` | string | 拓扑文件路径 | | `convertStatus` | string | 转换状态 | | `errorMessage` | string | 转换错误信息 | | `createdAt` | string | 创建时间 | | `updatedAt` | string | 更新时间 | ### 6.3 CadModelHistoryAnnotation | 字段 | 类型 | 说明 | | --- | --- | --- | | `id` | number | 标注 ID | | `modelId` | number | 模型 ID | | `historyId` | number | 建模历史 ID | | `modelingDescription` | string | 建模描述 | | `supplementDescription` | string | 补充描述 | | `remark` | string | 备注 | | `createdAt` | string | 创建时间 | | `updatedAt` | string | 更新时间 | ## 7. 前端联调注意事项 1. 所有 Path ID 都必须是正整数。 2. `POST` 更新类接口采用部分更新语义;字段未传表示不修改,字段传空字符串表示按空字符串更新。 3. 创建结构/功能时,关联 ID 数组必传且不能为空;更新结构/功能时,只有传入关联 ID 数组才会全量替换关系。 4. `historyIds` 和 `structureIds` 不能包含重复值;数组顺序会影响响应中的 `sortOrder`。 5. 结构、功能列表接口只返回未逻辑删除的数据。 6. 前端排查问题时可记录响应中的 `requestId`,便于后端按请求链路定位日志。