508 lines
13 KiB
Markdown
508 lines
13 KiB
Markdown
# API 文档 - 删除操作
|
||
|
||
## 元数据
|
||
- 需求编号:003-05
|
||
- 创建时间:2026-02-06
|
||
- 创建人:AI Assistant
|
||
- 状态:已完成
|
||
- 版本:v1.0.0
|
||
|
||
## API 概述
|
||
本文档描述了 Salesforce Metadata API 删除操作相关的 REST API 接口,包括元数据删除、批量删除和删除历史查询功能。
|
||
|
||
### 核心功能
|
||
1. **元数据删除**:根据元数据类型和完整名称删除单个或多个元数据
|
||
2. **批量删除**:支持批量删除不同类型的元数据,自动分批处理(每批 10 个)
|
||
3. **删除历史查询**:查询删除操作的历史记录
|
||
|
||
### 技术栈
|
||
- Spring Boot 2.7.x
|
||
- Spring Security(权限控制)
|
||
- MyBatis Plus(数据持久化)
|
||
- Salesforce Metadata API
|
||
|
||
### 基础路径
|
||
```
|
||
/salesforce/metadata/delete
|
||
```
|
||
|
||
## 接口列表
|
||
|
||
### 接口 1:删除元数据
|
||
|
||
#### 功能描述
|
||
根据元数据类型和完整名称列表删除元数据。支持一次删除多个同类型的元数据(最多 10 个,超过会自动分批处理)。
|
||
|
||
#### 请求方式
|
||
`POST`
|
||
|
||
#### 请求路径
|
||
```
|
||
/salesforce/metadata/delete/{type}
|
||
```
|
||
|
||
#### 权限要求
|
||
- 权限标识:`salesforce:metadata:delete`
|
||
- 使用 `@PreAuthorize("@ss.hasPermi('salesforce:metadata:delete')")` 控制
|
||
|
||
#### 请求参数
|
||
|
||
##### 路径参数
|
||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||
|--------|------|------|------|------|
|
||
| type | String | 是 | 元数据类型 | `CustomObject`、`ApexClass`、`ApexTrigger` |
|
||
|
||
##### 请求体参数
|
||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||
|--------|------|------|------|------|
|
||
| fullNames | String[] | 是 | 元数据完整名称列表 | `["MyCustomObject__c", "AnotherObject__c"]` |
|
||
|
||
#### 请求示例
|
||
```json
|
||
POST /salesforce/metadata/delete/CustomObject
|
||
Content-Type: application/json
|
||
|
||
["MyCustomObject__c", "AnotherObject__c"]
|
||
```
|
||
|
||
#### 响应参数
|
||
|
||
##### 成功响应(HTTP 200)
|
||
| 参数名 | 类型 | 说明 | 示例 |
|
||
|--------|------|------|------|
|
||
| code | Integer | 状态码,200 表示成功 | `200` |
|
||
| msg | String | 提示信息 | `"操作成功"` |
|
||
| data | Array | 删除结果列表 | 见下方示例 |
|
||
|
||
##### 删除结果对象(DeleteResultVo)
|
||
| 参数名 | 类型 | 说明 | 示例 |
|
||
|--------|------|------|------|
|
||
| fullName | String | 元数据完整名称 | `"MyCustomObject__c"` |
|
||
| success | Boolean | 是否删除成功 | `true` |
|
||
| errors | Array | 错误消息数组(失败时) | `["Entity is not found"]` |
|
||
|
||
#### 成功响应示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": [
|
||
{
|
||
"fullName": "MyCustomObject__c",
|
||
"success": true,
|
||
"errors": null
|
||
},
|
||
{
|
||
"fullName": "AnotherObject__c",
|
||
"success": false,
|
||
"errors": ["Entity is not found"]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### 失败响应示例
|
||
```json
|
||
{
|
||
"code": 500,
|
||
"msg": "Salesforce 连接失败: Connection refused"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 接口 2:批量删除元数据
|
||
|
||
#### 功能描述
|
||
批量删除不同类型的元数据。支持一次提交多个删除请求,每个请求包含元数据类型和完整名称列表。系统会自动对每个请求进行分批处理(每批 10 个)。
|
||
|
||
#### 请求方式
|
||
`POST`
|
||
|
||
#### 请求路径
|
||
```
|
||
/salesforce/metadata/delete/batch
|
||
```
|
||
|
||
#### 权限要求
|
||
- 权限标识:`salesforce:metadata:delete`
|
||
- 使用 `@PreAuthorize("@ss.hasPermi('salesforce:metadata:delete')")` 控制
|
||
|
||
#### 请求参数
|
||
|
||
##### 请求体参数(DeleteRequest 数组)
|
||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||
|--------|------|------|------|------|
|
||
| type | String | 是 | 元数据类型 | `CustomObject`、`ApexClass` |
|
||
| fullNames | String[] | 是 | 元数据完整名称列表 | `["Object1__c", "Object2__c"]` |
|
||
|
||
#### 请求示例
|
||
```json
|
||
POST /salesforce/metadata/delete/batch
|
||
Content-Type: application/json
|
||
|
||
[
|
||
{
|
||
"type": "CustomObject",
|
||
"fullNames": ["MyCustomObject__c", "AnotherObject__c"]
|
||
},
|
||
{
|
||
"type": "ApexClass",
|
||
"fullNames": ["MyApexClass", "AnotherClass"]
|
||
}
|
||
]
|
||
```
|
||
|
||
#### 响应参数
|
||
|
||
##### 成功响应(HTTP 200)
|
||
| 参数名 | 类型 | 说明 | 示例 |
|
||
|--------|------|------|------|
|
||
| code | Integer | 状态码,200 表示成功 | `200` |
|
||
| msg | String | 提示信息 | `"批量删除完成,成功 3 个,失败 1 个"` |
|
||
| data | Object | 批量删除结果 | 见下方示例 |
|
||
|
||
##### 批量删除结果对象
|
||
| 参数名 | 类型 | 说明 | 示例 |
|
||
|--------|------|------|------|
|
||
| totalCount | Integer | 总删除数量 | `4` |
|
||
| successCount | Integer | 成功数量 | `3` |
|
||
| failureCount | Integer | 失败数量 | `1` |
|
||
| results | Array | 详细删除结果列表 | DeleteResultVo 数组 |
|
||
|
||
#### 成功响应示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "批量删除完成,成功 3 个,失败 1 个",
|
||
"data": {
|
||
"totalCount": 4,
|
||
"successCount": 3,
|
||
"failureCount": 1,
|
||
"results": [
|
||
{
|
||
"fullName": "MyCustomObject__c",
|
||
"success": true,
|
||
"errors": null
|
||
},
|
||
{
|
||
"fullName": "AnotherObject__c",
|
||
"success": false,
|
||
"errors": ["Entity is not found"]
|
||
},
|
||
{
|
||
"fullName": "MyApexClass",
|
||
"success": true,
|
||
"errors": null
|
||
},
|
||
{
|
||
"fullName": "AnotherClass",
|
||
"success": true,
|
||
"errors": null
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 失败响应示例
|
||
```json
|
||
{
|
||
"code": 500,
|
||
"msg": "批量删除失败: 参数校验失败"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 接口 3:获取删除历史
|
||
|
||
#### 功能描述
|
||
查询元数据删除操作的历史记录,支持限制返回数量。
|
||
|
||
#### 请求方式
|
||
`GET`
|
||
|
||
#### 请求路径
|
||
```
|
||
/salesforce/metadata/delete/history
|
||
```
|
||
|
||
#### 权限要求
|
||
- 权限标识:`salesforce:metadata:delete:query`
|
||
- 使用 `@PreAuthorize("@ss.hasPermi('salesforce:metadata:delete:query')")` 控制
|
||
|
||
#### 请求参数
|
||
|
||
##### 查询参数
|
||
| 参数名 | 类型 | 必填 | 说明 | 默认值 | 范围 |
|
||
|--------|------|------|------|--------|------|
|
||
| limit | Integer | 否 | 返回记录数量限制 | `10` | 1-100 |
|
||
|
||
#### 请求示例
|
||
```
|
||
GET /salesforce/metadata/delete/history?limit=20
|
||
```
|
||
|
||
#### 响应参数
|
||
|
||
##### 成功响应(HTTP 200)
|
||
| 参数名 | 类型 | 说明 | 示例 |
|
||
|--------|------|------|------|
|
||
| code | Integer | 状态码,200 表示成功 | `200` |
|
||
| msg | String | 提示信息 | `"操作成功"` |
|
||
| data | Array | 删除历史记录列表 | 见下方示例 |
|
||
|
||
##### 删除历史记录对象(DataiMetadataDelete)
|
||
| 参数名 | 类型 | 说明 | 示例 |
|
||
|--------|------|------|------|
|
||
| id | Long | 记录 ID | `1` |
|
||
| metadataType | String | 元数据类型 | `CustomObject` |
|
||
| fullName | String | 元数据完整名称 | `MyCustomObject__c` |
|
||
| success | Integer | 是否成功(0-否,1-是) | `1` |
|
||
| errorMessage | String | 错误消息(失败时) | `null` |
|
||
| deleteTime | Date | 删除时间 | `2026-02-06 10:30:00` |
|
||
| userId | Long | 操作用户 ID | `1` |
|
||
| createBy | String | 创建者 | `admin` |
|
||
| createTime | Date | 创建时间 | `2026-02-06 10:30:00` |
|
||
|
||
#### 成功响应示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": [
|
||
{
|
||
"id": 1,
|
||
"metadataType": "CustomObject",
|
||
"fullName": "MyCustomObject__c",
|
||
"success": 1,
|
||
"errorMessage": null,
|
||
"deleteTime": "2026-02-06 10:30:00",
|
||
"userId": 1,
|
||
"createBy": "admin",
|
||
"createTime": "2026-02-06 10:30:00"
|
||
},
|
||
{
|
||
"id": 2,
|
||
"metadataType": "ApexClass",
|
||
"fullName": "MyApexClass",
|
||
"success": 0,
|
||
"errorMessage": "Entity is not found",
|
||
"deleteTime": "2026-02-06 10:35:00",
|
||
"userId": 1,
|
||
"createBy": "admin",
|
||
"createTime": "2026-02-06 10:35:00"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### 失败响应示例
|
||
```json
|
||
{
|
||
"code": 500,
|
||
"msg": "获取删除历史失败"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 错误码
|
||
|
||
### 系统错误码
|
||
| 错误码 | 说明 | 场景 |
|
||
|--------|------|------|
|
||
| 200 | 操作成功 | 请求处理成功 |
|
||
| 500 | 操作失败 | 服务器内部错误 |
|
||
| 401 | 未授权 | 用户未登录或 Token 过期 |
|
||
| 403 | 禁止访问 | 用户没有权限 |
|
||
| 404 | 资源不存在 | 请求的资源不存在 |
|
||
|
||
### 业务错误码
|
||
| 错误码 | 说明 | 场景 | 解决方案 |
|
||
|--------|------|------|----------|
|
||
| DELETE_001 | Salesforce 连接失败 | 连接 Salesforce 时发生异常 | 检查网络连接和 Salesforce 配置 |
|
||
| DELETE_002 | 删除元数据失败 | 调用 Salesforce API 删除失败 | 检查元数据是否存在,查看错误详情 |
|
||
| DELETE_003 | 批量删除失败 | 批量删除过程中发生错误 | 检查请求参数,查看具体错误信息 |
|
||
| DELETE_004 | 参数校验失败 | 请求参数不符合要求 | 检查参数是否为空,格式是否正确 |
|
||
|
||
---
|
||
|
||
## 数据模型
|
||
|
||
### DeleteRequest(删除请求)
|
||
```java
|
||
@Data
|
||
@Schema(description = "删除请求")
|
||
public class DeleteRequest implements Serializable {
|
||
private static final long serialVersionUID = 1L;
|
||
|
||
@NotBlank(message = "元数据类型不能为空")
|
||
@Schema(description = "元数据类型", required = true, example = "CustomObject")
|
||
private String type;
|
||
|
||
@NotEmpty(message = "元数据名称列表不能为空")
|
||
@Schema(description = "元数据完整名称列表", required = true, example = "[\"MyCustomObject__c\", \"AnotherObject__c\"]")
|
||
private String[] fullNames;
|
||
}
|
||
```
|
||
|
||
### DeleteResultVo(删除结果)
|
||
```java
|
||
@Data
|
||
@Schema(description = "删除结果")
|
||
public class DeleteResultVo implements Serializable {
|
||
private static final long serialVersionUID = 1L;
|
||
|
||
@Schema(description = "元数据完整名称", example = "MyCustomObject__c")
|
||
private String fullName;
|
||
|
||
@Schema(description = "是否删除成功", example = "true")
|
||
private boolean success;
|
||
|
||
@Schema(description = "错误消息数组", example = "[\"Entity is not found\"]")
|
||
private String[] errors;
|
||
}
|
||
```
|
||
|
||
### DataiMetadataDelete(删除历史实体)
|
||
```java
|
||
@Data
|
||
public class DataiMetadataDelete implements Serializable {
|
||
private static final long serialVersionUID = 1L;
|
||
|
||
private Long id;
|
||
private String metadataType;
|
||
private String fullName;
|
||
private Integer success;
|
||
private String errorMessage;
|
||
private Date deleteTime;
|
||
private Long userId;
|
||
private String createBy;
|
||
private Date createTime;
|
||
private String updateBy;
|
||
private Date updateTime;
|
||
private Integer delFlag;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 调用示例
|
||
|
||
### JavaScript 调用示例
|
||
|
||
#### 单个删除
|
||
```javascript
|
||
const response = await fetch('/salesforce/metadata/delete/CustomObject', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'Authorization': 'Bearer ' + token
|
||
},
|
||
body: JSON.stringify(['MyCustomObject__c'])
|
||
});
|
||
|
||
const result = await response.json();
|
||
console.log(result);
|
||
```
|
||
|
||
#### 批量删除
|
||
```javascript
|
||
const response = await fetch('/salesforce/metadata/delete/batch', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'Authorization': 'Bearer ' + token
|
||
},
|
||
body: JSON.stringify([
|
||
{ type: 'CustomObject', fullNames: ['Object1__c', 'Object2__c'] },
|
||
{ type: 'ApexClass', fullNames: ['Class1', 'Class2'] }
|
||
])
|
||
});
|
||
|
||
const result = await response.json();
|
||
console.log(result);
|
||
```
|
||
|
||
#### 查询历史
|
||
```javascript
|
||
const response = await fetch('/salesforce/metadata/delete/history?limit=10', {
|
||
method: 'GET',
|
||
headers: {
|
||
'Authorization': 'Bearer ' + token
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
console.log(result);
|
||
```
|
||
|
||
### Java 调用示例
|
||
|
||
#### 单个删除
|
||
```java
|
||
@RestController
|
||
public class DeleteExample {
|
||
|
||
@Autowired
|
||
private RestTemplate restTemplate;
|
||
|
||
public void deleteMetadata() {
|
||
String url = "http://localhost:8080/salesforce/metadata/delete/CustomObject";
|
||
|
||
HttpHeaders headers = new HttpHeaders();
|
||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||
headers.setBearerAuth(token);
|
||
|
||
String[] fullNames = {"MyCustomObject__c"};
|
||
HttpEntity<String[]> entity = new HttpEntity<>(fullNames, headers);
|
||
|
||
ResponseEntity<AjaxResult> response = restTemplate.exchange(
|
||
url, HttpMethod.POST, entity, AjaxResult.class);
|
||
|
||
System.out.println(response.getBody());
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 注意事项
|
||
|
||
### 1. 权限控制
|
||
- 所有接口都需要有效的 JWT Token
|
||
- 删除操作需要 `salesforce:metadata:delete` 权限
|
||
- 历史查询需要 `salesforce:metadata:delete:query` 权限
|
||
|
||
### 2. 分批处理
|
||
- Salesforce Metadata API 每次最多删除 10 个元数据
|
||
- 系统会自动对超过 10 个的请求进行分批处理
|
||
- 分批处理是串行执行,单个失败不影响其他批次
|
||
|
||
### 3. 异步日志
|
||
- 删除操作的历史记录是异步写入数据库的
|
||
- 可能会有短暂的延迟(通常 < 1 秒)
|
||
- 不影响主业务流程的响应时间
|
||
|
||
### 4. 错误处理
|
||
- 建议客户端对所有可能的错误码进行处理
|
||
- 对于批量删除,建议检查每个结果的 success 字段
|
||
- 对于失败的删除,可以根据 errors 字段进行针对性处理
|
||
|
||
### 5. 性能考虑
|
||
- 批量删除时,如果数量很大,可能需要较长时间
|
||
- 建议客户端设置合理的超时时间(如 60 秒)
|
||
- 对于超大量删除,建议分批调用接口
|
||
|
||
---
|
||
|
||
## 相关文档
|
||
- [需求文档](../requirements/sub/2026-01-28-003-05-删除操作.md)
|
||
- [设计文档](../design/2026-02-03-003-05-删除操作-设计.md)
|
||
- [决策记录](../decisions/2026-02-03-003-05-ADR-删除操作技术选型.md)
|
||
- [变更日志](../changelog/2026-02-06-003-05-changelog.md)
|
||
- [复盘文档](../retros/2026-02-06-003-05-retro.md)
|
||
- [会话记录](../sessions/2026-02-03-003-05-session.md)
|