Explorar o código

新增一个DDLparse的说明文档。

maxiaolong hai 3 días
pai
achega
305f7bfa75
Modificáronse 1 ficheiros con 467 adicións e 0 borrados
  1. 467 0
      docs/api_ddlparse_guide.md

+ 467 - 0
docs/api_ddlparse_guide.md

@@ -0,0 +1,467 @@
+# DDL解析接口 - 前端开发指南
+
+## 接口概述
+
+`/api/bd/ddlparse` 接口用于解析上传的文件,从中提取数据表结构定义信息。支持多种文件格式,适用于业务领域创建场景。
+
+## 接口信息
+
+| 属性 | 值 |
+|------|-----|
+| **URL** | `/api/bd/ddlparse` |
+| **方法** | `POST` |
+| **Content-Type** | `multipart/form-data` |
+| **认证** | 根据系统配置 |
+
+## 支持的文件类型
+
+| 文件类型 | 扩展名 | 说明 |
+|---------|--------|------|
+| SQL文件 | `.sql` | DDL建表语句,支持多表 |
+| Excel文件 | `.xlsx`, `.xls` | 表格形式的表结构定义 |
+| Word文件 | `.docx` | 文档形式的表结构定义(暂不支持 `.doc` 格式) |
+| PDF文件 | `.pdf` | PDF格式的表结构定义文档 |
+
+## 请求参数
+
+### Form Data
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| `file` | File | 是 | 上传的文件,每次只能上传一个文件 |
+
+## 响应格式
+
+### 成功响应
+
+```json
+{
+  "code": 200,
+  "message": "操作成功",
+  "data": [
+    {
+      "table_info": {
+        "name_zh": "用户信息表",
+        "name_en": "user_info"
+      },
+      "columns": [
+        {
+          "name_zh": "用户ID",
+          "name_en": "user_id",
+          "data_type": "INTEGER",
+          "is_primary": "是",
+          "comment": "用户唯一标识",
+          "nullable": "否"
+        },
+        {
+          "name_zh": "用户名",
+          "name_en": "username",
+          "data_type": "VARCHAR(50)",
+          "is_primary": "否",
+          "comment": "用户登录名",
+          "nullable": "否"
+        }
+      ],
+      "exist": false
+    }
+  ]
+}
+```
+
+### 响应字段说明
+
+#### 顶层结构
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `code` | number | 状态码,200表示成功 |
+| `message` | string | 操作结果消息 |
+| `data` | array | 解析出的表结构数组,**始终为数组格式** |
+
+#### 表结构对象 (data 数组元素)
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `table_info` | object | 表的基本信息 |
+| `table_info.name_zh` | string | 表的中文名称 |
+| `table_info.name_en` | string | 表的英文名称 |
+| `columns` | array | 字段列表 |
+| `exist` | boolean | 该表在系统中是否已存在 |
+
+#### 字段对象 (columns 数组元素)
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `name_zh` | string | 字段中文名称 |
+| `name_en` | string | 字段英文名称 |
+| `data_type` | string | 数据类型(如 VARCHAR(50)、INTEGER) |
+| `is_primary` | string | 是否主键:"是" 或 "否" |
+| `comment` | string | 字段注释/说明 |
+| `nullable` | string | 是否可为空:"是" 或 "否" |
+
+### 错误响应
+
+```json
+{
+  "code": 500,
+  "message": "错误描述信息",
+  "error": "详细错误信息(可选)"
+}
+```
+
+#### 常见错误
+
+| 错误消息 | 原因 |
+|---------|------|
+| `没有找到上传的文件,请上传一个文件` | 请求中没有包含文件 |
+| `未选择文件` | 文件字段为空 |
+| `不支持的文件类型: .xxx` | 上传了不支持的文件格式 |
+| `暂不支持 .doc 格式,请转换为 .docx 格式后重新上传` | 上传了旧版 Word 格式 |
+| `未找到有效的数据表定义信息` | 文件中没有识别到表结构 |
+
+## 前端代码示例
+
+### Vue 3 + Element Plus
+
+```vue
+<template>
+  <el-upload
+    ref="uploadRef"
+    :auto-upload="false"
+    :limit="1"
+    :on-change="handleFileChange"
+    :on-exceed="handleExceed"
+    accept=".sql,.xlsx,.xls,.docx,.pdf"
+  >
+    <template #trigger>
+      <el-button type="primary">选择文件</el-button>
+    </template>
+    <el-button 
+      type="success" 
+      @click="submitUpload"
+      :loading="loading"
+      style="margin-left: 10px"
+    >
+      解析文件
+    </el-button>
+    <template #tip>
+      <div class="el-upload__tip">
+        支持 .sql、.xlsx、.xls、.docx、.pdf 格式,单次仅支持上传一个文件
+      </div>
+    </template>
+  </el-upload>
+
+  <!-- 解析结果展示 -->
+  <div v-if="tableList.length > 0" class="result-section">
+    <h3>解析结果(共 {{ tableList.length }} 个表)</h3>
+    <el-collapse v-model="activeNames">
+      <el-collapse-item 
+        v-for="(table, index) in tableList" 
+        :key="index"
+        :name="index"
+      >
+        <template #title>
+          <span>
+            {{ table.table_info.name_zh || table.table_info.name_en }}
+            <el-tag v-if="table.exist" type="warning" size="small">已存在</el-tag>
+          </span>
+        </template>
+        <el-table :data="table.columns" stripe>
+          <el-table-column prop="name_zh" label="字段中文名" />
+          <el-table-column prop="name_en" label="字段英文名" />
+          <el-table-column prop="data_type" label="数据类型" />
+          <el-table-column prop="is_primary" label="主键" width="80" />
+          <el-table-column prop="nullable" label="可空" width="80" />
+          <el-table-column prop="comment" label="备注" />
+        </el-table>
+      </el-collapse-item>
+    </el-collapse>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { ElMessage } from 'element-plus'
+import axios from 'axios'
+
+const uploadRef = ref()
+const loading = ref(false)
+const currentFile = ref(null)
+const tableList = ref([])
+const activeNames = ref([0])
+
+const handleFileChange = (file) => {
+  currentFile.value = file.raw
+}
+
+const handleExceed = () => {
+  ElMessage.warning('每次只能上传一个文件')
+}
+
+const submitUpload = async () => {
+  if (!currentFile.value) {
+    ElMessage.warning('请先选择文件')
+    return
+  }
+
+  const formData = new FormData()
+  formData.append('file', currentFile.value)
+
+  loading.value = true
+  try {
+    const response = await axios.post('/api/bd/ddlparse', formData, {
+      headers: {
+        'Content-Type': 'multipart/form-data'
+      }
+    })
+
+    if (response.data.code === 200) {
+      tableList.value = response.data.data
+      ElMessage.success(`解析成功,共识别到 ${tableList.value.length} 个表`)
+    } else {
+      ElMessage.error(response.data.message || '解析失败')
+    }
+  } catch (error) {
+    ElMessage.error('请求失败:' + (error.message || '未知错误'))
+  } finally {
+    loading.value = false
+  }
+}
+</script>
+
+<style scoped>
+.result-section {
+  margin-top: 20px;
+}
+</style>
+```
+
+### React + Ant Design
+
+```tsx
+import React, { useState } from 'react';
+import { Upload, Button, message, Collapse, Table, Tag, Space } from 'antd';
+import { UploadOutlined, FileSearchOutlined } from '@ant-design/icons';
+import type { UploadFile } from 'antd/es/upload/interface';
+import axios from 'axios';
+
+interface Column {
+  name_zh: string;
+  name_en: string;
+  data_type: string;
+  is_primary: string;
+  comment: string;
+  nullable: string;
+}
+
+interface TableInfo {
+  table_info: {
+    name_zh: string;
+    name_en: string;
+  };
+  columns: Column[];
+  exist: boolean;
+}
+
+const DDLParseUpload: React.FC = () => {
+  const [fileList, setFileList] = useState<UploadFile[]>([]);
+  const [loading, setLoading] = useState(false);
+  const [tableList, setTableList] = useState<TableInfo[]>([]);
+
+  const handleUpload = async () => {
+    if (fileList.length === 0) {
+      message.warning('请先选择文件');
+      return;
+    }
+
+    const formData = new FormData();
+    formData.append('file', fileList[0] as any);
+
+    setLoading(true);
+    try {
+      const response = await axios.post('/api/bd/ddlparse', formData, {
+        headers: { 'Content-Type': 'multipart/form-data' }
+      });
+
+      if (response.data.code === 200) {
+        setTableList(response.data.data);
+        message.success(`解析成功,共识别到 ${response.data.data.length} 个表`);
+      } else {
+        message.error(response.data.message || '解析失败');
+      }
+    } catch (error: any) {
+      message.error('请求失败:' + (error.message || '未知错误'));
+    } finally {
+      setLoading(false);
+    }
+  };
+
+  const columns = [
+    { title: '字段中文名', dataIndex: 'name_zh', key: 'name_zh' },
+    { title: '字段英文名', dataIndex: 'name_en', key: 'name_en' },
+    { title: '数据类型', dataIndex: 'data_type', key: 'data_type' },
+    { title: '主键', dataIndex: 'is_primary', key: 'is_primary', width: 80 },
+    { title: '可空', dataIndex: 'nullable', key: 'nullable', width: 80 },
+    { title: '备注', dataIndex: 'comment', key: 'comment' },
+  ];
+
+  return (
+    <div>
+      <Space>
+        <Upload
+          fileList={fileList}
+          beforeUpload={(file) => {
+            setFileList([file]);
+            return false;
+          }}
+          onRemove={() => setFileList([])}
+          accept=".sql,.xlsx,.xls,.docx,.pdf"
+          maxCount={1}
+        >
+          <Button icon={<UploadOutlined />}>选择文件</Button>
+        </Upload>
+        <Button
+          type="primary"
+          onClick={handleUpload}
+          loading={loading}
+          icon={<FileSearchOutlined />}
+        >
+          解析文件
+        </Button>
+      </Space>
+      <p style={{ color: '#999', fontSize: 12, marginTop: 8 }}>
+        支持 .sql、.xlsx、.xls、.docx、.pdf 格式
+      </p>
+
+      {tableList.length > 0 && (
+        <div style={{ marginTop: 20 }}>
+          <h3>解析结果(共 {tableList.length} 个表)</h3>
+          <Collapse
+            items={tableList.map((table, index) => ({
+              key: index,
+              label: (
+                <span>
+                  {table.table_info.name_zh || table.table_info.name_en}
+                  {table.exist && <Tag color="warning" style={{ marginLeft: 8 }}>已存在</Tag>}
+                </span>
+              ),
+              children: (
+                <Table
+                  dataSource={table.columns}
+                  columns={columns}
+                  rowKey="name_en"
+                  size="small"
+                  pagination={false}
+                />
+              ),
+            }))}
+            defaultActiveKey={[0]}
+          />
+        </div>
+      )}
+    </div>
+  );
+};
+
+export default DDLParseUpload;
+```
+
+### 原生 JavaScript (Fetch API)
+
+```javascript
+async function parseDDLFile(file) {
+  const formData = new FormData();
+  formData.append('file', file);
+
+  try {
+    const response = await fetch('/api/bd/ddlparse', {
+      method: 'POST',
+      body: formData
+    });
+
+    const result = await response.json();
+
+    if (result.code === 200) {
+      console.log('解析成功,表数量:', result.data.length);
+      return result.data;
+    } else {
+      throw new Error(result.message);
+    }
+  } catch (error) {
+    console.error('解析失败:', error);
+    throw error;
+  }
+}
+
+// 使用示例
+document.getElementById('fileInput').addEventListener('change', async (e) => {
+  const file = e.target.files[0];
+  if (!file) return;
+
+  try {
+    const tables = await parseDDLFile(file);
+    // 处理解析结果
+    tables.forEach(table => {
+      console.log('表名:', table.table_info.name_zh);
+      console.log('字段数:', table.columns.length);
+      console.log('是否已存在:', table.exist);
+    });
+  } catch (error) {
+    alert('解析失败: ' + error.message);
+  }
+});
+```
+
+## 文件格式建议
+
+### SQL 文件
+
+标准的 DDL 建表语句,支持多表:
+
+```sql
+CREATE TABLE user_info (
+    user_id INT PRIMARY KEY COMMENT '用户ID',
+    username VARCHAR(50) NOT NULL COMMENT '用户名',
+    email VARCHAR(100) COMMENT '邮箱地址'
+);
+
+CREATE TABLE order_info (
+    order_id BIGINT PRIMARY KEY COMMENT '订单ID',
+    user_id INT NOT NULL COMMENT '用户ID',
+    total_amount DECIMAL(10,2) COMMENT '订单金额'
+);
+```
+
+### Excel 文件
+
+建议使用表格形式,包含以下列:
+
+| 字段英文名 | 字段中文名 | 数据类型 | 是否主键 | 是否可空 | 备注 |
+|-----------|-----------|---------|---------|---------|------|
+| user_id | 用户ID | INTEGER | 是 | 否 | 用户唯一标识 |
+| username | 用户名 | VARCHAR(50) | 否 | 否 | 登录名 |
+
+### Word 文件
+
+文档中包含表格形式的字段定义,系统会自动识别文档中的表格并解析。
+
+### PDF 文件
+
+PDF 中包含的表结构定义文本或表格,系统会提取文本和表格内容进行解析。
+
+## 注意事项
+
+1. **文件大小限制**:建议单个文件不超过 10MB
+2. **编码格式**:SQL 文件建议使用 UTF-8 编码
+3. **单次上传**:每次请求只能上传一个文件
+4. **解析时间**:由于使用 LLM 进行智能解析,复杂文档可能需要几秒钟
+5. **exist 字段**:表示该表名是否在系统的业务领域中已存在,用于提示用户避免重复创建
+6. **Word 格式**:仅支持 `.docx` 格式,旧版 `.doc` 格式需要转换后上传
+
+## 更新日志
+
+| 版本 | 日期 | 更新内容 |
+|------|------|---------|
+| v1.1.0 | 2025-12-26 | 新增 Excel、Word、PDF 文件支持 |
+| v1.0.0 | - | 初始版本,仅支持 SQL 文件 |
+