# 业务领域 API 接口文档

> 本文档为前端开发人员提供业务领域（Business Domain）模块的 API 接口说明。

## 目录

- [通用说明](#通用说明)
- [接口列表](#接口列表)
  - [1. 获取业务领域列表](#1-获取业务领域列表)
  - [2. 获取业务领域详情](#2-获取业务领域详情)
  - [3. 删除业务领域](#3-删除业务领域)
  - [4. 保存业务领域](#4-保存业务领域)
  - [5. 更新业务领域](#5-更新业务领域)
  - [6. 上传文件](#6-上传文件)
  - [7. 下载文件](#7-下载文件)
  - [8. 获取关系图谱](#8-获取关系图谱)
  - [9. 解析DDL语句](#9-解析ddl语句)
  - [10. 搜索关联元数据](#10-搜索关联元数据)
  - [11. 组合创建业务领域](#11-组合创建业务领域)
  - [12. 获取标签列表](#12-获取标签列表)
- [错误码说明](#错误码说明)

---

## 通用说明

### 基础URL

```
/api/bd
```

### 统一响应格式

**成功响应：**

```json
{
  "code": 200,
  "message": "操作成功",
  "data": { ... }
}
```

**失败响应：**

```json
{
  "code": 500,
  "message": "错误描述",
  "data": null,
  "error": "详细错误信息"
}
```

### 请求头

大部分接口需要设置 `Content-Type`:

```
Content-Type: application/json
```

文件上传接口需要设置:

```
Content-Type: multipart/form-data
```

---

## 接口列表

### 1. 获取业务领域列表

获取业务领域的分页列表，支持多种过滤条件。

**请求URL：** `POST /api/bd/list`

**请求参数：**

| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| current | integer | 否 | 1 | 当前页码 |
| size | integer | 否 | 10 | 每页大小 |
| name_en | string | 否 | - | 英文名称过滤条件 |
| name_zh | string | 否 | - | 中文名称过滤条件 |
| type | string | 否 | "all" | 类型过滤条件，"all"表示不过滤 |
| category | string | 否 | - | 分类过滤条件 |
| tag | string | 否 | - | 标签过滤条件 |

**返回参数：**

| 参数名 | 类型 | 说明 |
|--------|------|------|
| code | integer | 状态码 |
| message | string | 消息 |
| data.records | array | 业务领域列表 |
| data.total | integer | 总数量 |
| data.size | integer | 每页大小 |
| data.current | integer | 当前页码 |

**请求示例：**

```javascript
// JavaScript (fetch)
const response = await fetch('/api/bd/list', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    current: 1,
    size: 10,
    name_zh: "订单"
  })
});
const data = await response.json();
```

```javascript
// JavaScript (axios)
const { data } = await axios.post('/api/bd/list', {
  current: 1,
  size: 10,
  name_zh: "订单"
});
```

**返回示例：**

```json
{
  "code": 200,
  "message": "操作成功",
  "data": {
    "records": [
      {
        "id": 12345,
        "name_zh": "订单管理",
        "name_en": "order_management",
        "type": "table",
        "category": "业务",
        "describe": "订单管理业务领域",
        "create_time": "2024-01-15 10:30:00"
      }
    ],
    "total": 100,
    "size": 10,
    "current": 1
  }
}
```

**错误响应：**

```json
{
  "code": 500,
  "message": "获取业务领域列表失败",
  "data": null,
  "error": "Database connection failed"
}
```

---

### 2. 获取业务领域详情

根据ID获取单个业务领域的详细信息。

**请求URL：** `POST /api/bd/detail`

**请求参数：**

| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| id | integer | 是 | 业务领域节点ID |

**返回参数：**

| 参数名 | 类型 | 说明 |
|--------|------|------|
| code | integer | 状态码 |
| message | string | 消息 |
| data | object | 业务领域详情对象 |

**请求示例：**

```javascript
// JavaScript (fetch)
const response = await fetch('/api/bd/detail', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    id: 12345
  })
});
const data = await response.json();
```

```javascript
// JavaScript (axios)
const { data } = await axios.post('/api/bd/detail', {
  id: 12345
});
```

**返回示例：**

```json
{
  "code": 200,
  "message": "操作成功",
  "data": {
    "id": 12345,
    "name_zh": "订单管理",
    "name_en": "order_management",
    "type": "table",
    "category": "业务",
    "describe": "订单管理业务领域",
    "tag": 100,
    "data_source": 200,
    "create_time": "2024-01-15 10:30:00",
    "update_time": "2024-01-16 14:20:00"
  }
}
```

**错误码：**

| code | message | 说明 |
|------|---------|------|
| 500 | 请求数据不能为空 | 未提供请求体 |
| 500 | 业务领域ID不能为空 | id参数缺失 |
| 500 | 业务领域ID必须为整数 | id格式错误 |
| 500 | 业务领域不存在 | 找不到对应记录 |

---

### 3. 删除业务领域

根据ID删除业务领域。

**请求URL：** `POST /api/bd/delete`

**请求参数：**

| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| id | integer | 是 | 业务领域节点ID |

**返回参数：**

| 参数名 | 类型 | 说明 |
|--------|------|------|
| code | integer | 状态码 |
| message | string | 消息 |
| data.message | string | 删除结果描述 |

**请求示例：**

```javascript
// JavaScript (axios)
const { data } = await axios.post('/api/bd/delete', {
  id: 12345
});
```

**返回示例：**

```json
{
  "code": 200,
  "message": "操作成功",
  "data": {
    "message": "业务领域删除成功"
  }
}
```

**错误码：**

| code | message | 说明 |
|------|---------|------|
| 500 | 请求数据不能为空 | 未提供请求体 |
| 500 | 业务领域ID不能为空 | id参数缺失 |
| 500 | 业务领域删除失败 | 删除操作失败 |

---

### 4. 保存业务领域

保存业务领域，支持新建和更新两种模式。

**请求URL：** `POST /api/bd/save`

**请求参数：**

| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| id | integer | 否 | 业务领域ID（有则更新，无则新建） |
| name_zh | string | 新建时必填 | 中文名称 |
| name_en | string | 新建时必填 | 英文名称 |
| describe | string | 否 | 描述 |
| type | string | 否 | 类型 |
| category | string | 否 | 分类 |
| tag | integer | 否 | 标签ID |
| data_source | integer | 否 | 数据源ID |

**返回参数：**

| 参数名 | 类型 | 说明 |
|--------|------|------|
| code | integer | 状态码 |
| message | string | 消息 |
| data | object | 保存后的业务领域数据 |

**请求示例：**

```javascript
// 新建
const { data } = await axios.post('/api/bd/save', {
  name_zh: "客户管理",
  name_en: "customer_management",
  type: "table",
  category: "业务",
  describe: "客户信息管理业务领域"
});

// 更新
const { data } = await axios.post('/api/bd/save', {
  id: 12345,
  describe: "更新后的描述"
});
```

**返回示例：**

```json
{
  "code": 200,
  "message": "操作成功",
  "data": {
    "id": 12346,
    "name_zh": "客户管理",
    "name_en": "customer_management",
    "type": "table",
    "category": "业务",
    "describe": "客户信息管理业务领域",
    "create_time": "2024-01-17 09:00:00"
  }
}
```

**错误码：**

| code | message | 说明 |
|------|---------|------|
| 500 | 请求数据不能为空 | 未提供请求体 |
| 500 | 新建时 name_zh 和 name_en 为必填项 | 新建时缺少必填字段 |

---

### 5. 更新业务领域

更新已存在的业务领域。

**请求URL：** `POST /api/bd/update`

**请求参数：**

| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| id | integer | 是 | 业务领域节点ID |
| name_zh | string | 否 | 中文名称 |
| name_en | string | 否 | 英文名称 |
| describe | string | 否 | 描述 |
| tag | integer | 否 | 标签ID |
| data_source | integer | 否 | 数据源ID |

**请求示例：**

```javascript
const { data } = await axios.post('/api/bd/update', {
  id: 12345,
  name_zh: "订单管理系统",
  describe: "更新后的描述信息"
});
```

**返回示例：**

```json
{
  "code": 200,
  "message": "操作成功",
  "data": {
    "id": 12345,
    "name_zh": "订单管理系统",
    "name_en": "order_management",
    "describe": "更新后的描述信息",
    "update_time": "2024-01-17 10:30:00"
  }
}
```

**错误码：**

| code | message | 说明 |
|------|---------|------|
| 500 | 参数不完整 | 未提供id参数 |

---

### 6. 上传文件

上传业务领域相关文件到对象存储。

**请求URL：** `POST /api/bd/upload`

**Content-Type：** `multipart/form-data`

**请求参数：**

| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| file | File | 是 | 上传的文件 |

**返回参数：**

| 参数名 | 类型 | 说明 |
|--------|------|------|
| data.filename | string | 原始文件名 |
| data.size | integer | 文件大小（字节） |
| data.type | string | 文件类型（扩展名） |
| data.url | string | 文件存储路径 |

**请求示例：**

```javascript
// JavaScript (FormData)
const formData = new FormData();
formData.append('file', fileInput.files[0]);

const response = await fetch('/api/bd/upload', {
  method: 'POST',
  body: formData
});
const data = await response.json();
```

```javascript
// JavaScript (axios)
const formData = new FormData();
formData.append('file', file);

const { data } = await axios.post('/api/bd/upload', formData, {
  headers: {
    'Content-Type': 'multipart/form-data'
  }
});
```

**返回示例：**

```json
{
  "code": 200,
  "message": "操作成功",
  "data": {
    "filename": "schema.sql",
    "size": 2048,
    "type": "sql",
    "url": "business_domain/schema_20240117103000.sql"
  }
}
```

**错误码：**

| code | message | 说明 |
|------|---------|------|
| 500 | 没有找到上传的文件 | 请求中无file字段 |
| 500 | 未选择文件 | 文件名为空 |
| 500 | 不支持的文件类型 | 文件扩展名不在允许列表中 |

---

### 7. 下载文件

下载业务领域相关文件。

**请求URL：** `GET /api/bd/download`

**请求参数（Query String）：**

| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| url | string | 是 | 文件存储路径（从上传接口返回） |

**返回：**

成功时返回文件流（作为附件下载），失败时返回 JSON 错误信息。

**请求示例：**

```javascript
// 方式1：直接打开链接下载
window.open('/api/bd/download?url=business_domain/schema_20240117103000.sql');

// 方式2：使用fetch下载
const response = await fetch('/api/bd/download?url=' + encodeURIComponent(fileUrl));
if (response.ok) {
  const blob = await response.blob();
  const url = window.URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'filename.sql';
  a.click();
}
```

**错误码：**

| code | message | 说明 |
|------|---------|------|
| 500 | 文件路径不能为空 | 未提供url参数 |
| 500 | 文件获取失败 | MinIO获取文件失败 |

---

### 8. 获取关系图谱

获取业务领域的完整关系图谱数据，用于可视化展示。

**请求URL：** `POST /api/bd/graphall`

**请求参数：**

| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| id | integer | 是 | - | 业务领域节点ID |
| meta | boolean | 否 | true | 是否包含元数据节点 |

**返回参数：**

| 参数名 | 类型 | 说明 |
|--------|------|------|
| data.nodes | array | 节点列表 |
| data.lines | array | 关系列表 |

**请求示例：**

```javascript
const { data } = await axios.post('/api/bd/graphall', {
  id: 12345,
  meta: true
});
```

**返回示例：**

```json
{
  "code": 200,
  "message": "操作成功",
  "data": {
    "nodes": [
      {
        "id": 12345,
        "name": "订单管理",
        "type": "BusinessDomain",
        "properties": { ... }
      },
      {
        "id": 12346,
        "name": "order_id",
        "type": "MetaData",
        "properties": { ... }
      }
    ],
    "lines": [
      {
        "from": 12345,
        "to": 12346,
        "type": "HAS_METADATA",
        "properties": { ... }
      }
    ]
  }
}
```

**错误码：**

| code | message | 说明 |
|------|---------|------|
| 500 | 请求数据不能为空 | 未提供请求体 |
| 500 | 业务领域ID不能为空 | id参数缺失 |
| 500 | 业务领域ID必须为整数 | id格式错误 |

---

### 9. 解析DDL语句

解析 SQL DDL 语句，提取表结构信息，用于快速创建业务领域。

**请求URL：** `POST /api/bd/ddlparse`

**请求方式：**

支持两种方式提交 DDL：

1. **文件上传方式** (`multipart/form-data`)
2. **JSON方式** (`application/json`)

**请求参数（文件上传方式）：**

| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| file | File | 是 | SQL文件（.sql扩展名） |

**请求参数（JSON方式）：**

| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| sql | string | 是 | SQL DDL 内容 |

**返回参数：**

| 参数名 | 类型 | 说明 |
|--------|------|------|
| data | array | 解析后的DDL列表，包含表信息和字段信息 |
| data[].table_info | object | 表信息 |
| data[].columns | array | 字段列表 |
| data[].exist | boolean | 表是否已存在于系统中 |

**请求示例：**

```javascript
// 方式1：文件上传
const formData = new FormData();
formData.append('file', sqlFile);

const { data } = await axios.post('/api/bd/ddlparse', formData, {
  headers: {
    'Content-Type': 'multipart/form-data'
  }
});

// 方式2：JSON提交
const { data } = await axios.post('/api/bd/ddlparse', {
  sql: `
    CREATE TABLE orders (
      id INT PRIMARY KEY,
      customer_id INT,
      amount DECIMAL(10,2),
      create_time DATETIME
    );
  `
});
```

**返回示例：**

```json
{
  "code": 200,
  "message": "操作成功",
  "data": [
    {
      "table_info": {
        "name_en": "orders",
        "name_zh": "订单表",
        "comment": "订单信息表"
      },
      "columns": [
        {
          "name_en": "id",
          "name_zh": "主键",
          "data_type": "INT",
          "is_primary": true,
          "comment": "主键ID"
        },
        {
          "name_en": "customer_id",
          "name_zh": "客户ID",
          "data_type": "INT",
          "is_primary": false,
          "comment": "关联客户ID"
        }
      ],
      "exist": false
    }
  ]
}
```

**错误码：**

| code | message | 说明 |
|------|---------|------|
| 500 | 只接受SQL文件 | 上传的文件不是.sql格式 |
| 500 | SQL内容不能为空 | 未提供SQL内容 |
| 500 | 未找到有效的CREATE TABLE语句 | DDL解析失败 |

---

### 10. 搜索关联元数据

搜索与业务领域关联的元数据列表。

**请求URL：** `POST /api/bd/search`

**请求参数：**

| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| id | integer | 是 | - | 业务领域节点ID |
| current | integer | 否 | 1 | 当前页码 |
| size | integer | 否 | 10 | 每页大小 |
| name_en | string | 否 | - | 英文名称过滤条件 |
| name_zh | string | 否 | - | 中文名称过滤条件 |
| category | string | 否 | - | 分类过滤条件 |
| tag | string | 否 | - | 标签过滤条件 |

**返回参数：**

| 参数名 | 类型 | 说明 |
|--------|------|------|
| data.records | array | 元数据列表 |
| data.total | integer | 总数量 |
| data.size | integer | 每页大小 |
| data.current | integer | 当前页码 |

**请求示例：**

```javascript
const { data } = await axios.post('/api/bd/search', {
  id: 12345,
  current: 1,
  size: 20,
  name_zh: "订单"
});
```

**返回示例：**

```json
{
  "code": 200,
  "message": "操作成功",
  "data": {
    "records": [
      {
        "id": 23456,
        "name_zh": "订单ID",
        "name_en": "order_id",
        "data_type": "INT",
        "category": "主键",
        "create_time": "2024-01-15 10:30:00"
      }
    ],
    "total": 50,
    "size": 20,
    "current": 1
  }
}
```

**错误码：**

| code | message | 说明 |
|------|---------|------|
| 500 | 请求数据不能为空 | 未提供请求体 |
| 500 | 业务领域ID不能为空 | id参数缺失 |
| 500 | 业务领域ID必须为整数 | id格式错误 |

---

### 11. 组合创建业务领域

从已有的元数据中组合创建新的业务领域。

> 📖 详细开发指南请参考：[api_bd_compose_guide.md](./api_bd_compose_guide.md)

**请求URL：** `POST /api/bd/compose`

**请求参数：**

| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| name_zh | string | 是 | 中文名称 |
| name_en | string | 否 | 英文名称（不提供则自动翻译） |
| id_list | array | 是 | 选中的元数据ID列表 |
| describe | string | 否 | 描述 |
| type | string | 否 | 类型 |
| category | string | 否 | 分类 |
| tag | integer/array | 否 | 标签ID或标签ID数组 |
| data_source | integer | 否 | 数据源ID |

**id_list 格式：**

支持两种格式：

```json
// 格式一：纯ID数组（推荐）
[123, 456, 789]

// 格式二：对象数组
[{ "id": 123 }, { "id": 456 }, { "id": 789 }]
```

**请求示例：**

```javascript
const { data } = await axios.post('/api/bd/compose', {
  name_zh: "销售分析域",
  name_en: "sales_analysis",
  describe: "整合订单和客户数据的销售分析业务领域",
  id_list: [23456, 23457, 23458]  // 直接传递元数据ID列表
});
```

**返回示例：**

```json
{
  "code": 200,
  "message": "操作成功",
  "data": {
    "business_domain": {
      "id": 12350,
      "name_zh": "销售分析域",
      "name_en": "sales_analysis",
      "describe": "整合订单和客户数据的销售分析业务领域",
      "create_time": "2025-01-09 11:00:00",
      "tag": []
    }
  }
}
```

**错误码：**

| code | message | 说明 |
|------|---------|------|
| 500 | 请求数据不能为空 | 未提供请求体 |
| 500 | name_zh 为必填项 | 缺少中文名称 |
| 500 | id_list 为必填项 | 缺少元数据ID列表 |

---

### 12. 获取标签列表

获取可用于业务领域关联的数据标签列表。

**请求URL：** `POST /api/bd/labellist`

**请求参数：**

| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| current | integer | 否 | 1 | 当前页码 |
| size | integer | 否 | 10 | 每页大小 |
| name_en | string | 否 | - | 英文名称过滤条件 |
| name_zh | string | 否 | - | 中文名称过滤条件 |
| category | string | 否 | - | 分类过滤条件 |
| group | string | 否 | - | 分组过滤条件 |

**返回参数：**

| 参数名 | 类型 | 说明 |
|--------|------|------|
| data.records | array | 标签列表 |
| data.total | integer | 总数量 |
| data.size | integer | 每页大小 |
| data.current | integer | 当前页码 |

**请求示例：**

```javascript
const { data } = await axios.post('/api/bd/labellist', {
  current: 1,
  size: 20,
  category: "业务标签"
});
```

**返回示例：**

```json
{
  "code": 200,
  "message": "操作成功",
  "data": {
    "records": [
      {
        "id": 100,
        "name_zh": "核心业务",
        "name_en": "core_business",
        "category": "业务标签",
        "group": "优先级",
        "create_time": "2024-01-10 09:00:00"
      }
    ],
    "total": 30,
    "size": 20,
    "current": 1
  }
}
```

**错误码：**

| code | message | 说明 |
|------|---------|------|
| 500 | 请求数据不能为空 | 未提供请求体 |

---

## 错误码说明

### 通用错误码

| code | 说明 |
|------|------|
| 200 | 请求成功 |
| 500 | 服务器内部错误 |

### 常见错误消息

| message | 说明 | 解决方案 |
|---------|------|----------|
| 请求数据不能为空 | 未提供请求体或请求体为空 | 确保发送有效的JSON请求体 |
| 业务领域ID不能为空 | 必填参数id缺失 | 添加id参数 |
| 业务领域ID必须为整数 | id参数类型错误 | 确保id为整数类型 |
| 业务领域不存在 | 指定ID的记录不存在 | 检查ID是否正确 |
| 参数不完整 | 缺少必填参数 | 检查请求参数完整性 |
| 新建时 name_zh 和 name_en 为必填项 | 新建时缺少必填字段 | 添加name_zh和name_en参数 |
| 不支持的文件类型 | 上传文件类型不在允许列表中 | 检查文件扩展名 |

---

## 更新日志

| 版本 | 日期 | 更新内容 |
|------|------|----------|
| 1.0.0 | 2025-12-06 | 初始版本 |

