|
@@ -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 文件 |
|
|
|
|
|
+
|