|
|
@@ -3,46 +3,38 @@
|
|
|
<v-card class="db-box d-flex flex-column" elevation="5" v-loading="loadingUpload">
|
|
|
<v-banner single-line>
|
|
|
<div class="d-flex align-center">
|
|
|
- <!-- <div class="py-2 title">DDL解析</div> -->
|
|
|
- <v-tabs v-model="uploadTab" @change="handleTabChange">
|
|
|
- <v-tab>DDL解析</v-tab>
|
|
|
- <v-tab>Excel解析</v-tab>
|
|
|
- <v-tab>文本解析</v-tab>
|
|
|
- </v-tabs>
|
|
|
+ <div class="pa-2 title">文件解析</div>
|
|
|
<v-spacer></v-spacer>
|
|
|
- <upload-btn
|
|
|
+ <UploadBtn
|
|
|
text
|
|
|
color="primary"
|
|
|
+ accept=".sql,.docx,.xls,.xlsx,.pdf"
|
|
|
@change="handleChangeFile"
|
|
|
>
|
|
|
<v-icon left>mdi-import</v-icon>
|
|
|
- {{ uploadBtnText }}
|
|
|
- </upload-btn>
|
|
|
+ 导入文件
|
|
|
+ </UploadBtn>
|
|
|
</div>
|
|
|
</v-banner>
|
|
|
- <v-tabs-items v-model="uploadTab">
|
|
|
- <!-- DDL解析 -->
|
|
|
- <v-tab-item>
|
|
|
- <DDLPage
|
|
|
- :items="items"
|
|
|
- :origin="origin"
|
|
|
- :select="select"
|
|
|
- @select="handleSelect"
|
|
|
- ></DDLPage>
|
|
|
- </v-tab-item>
|
|
|
- <!-- EXCEL解析 -->
|
|
|
- <v-tab-item>
|
|
|
- <ExcelPage
|
|
|
- ref="excelPage"
|
|
|
- style="position: relative;height: 100%;"
|
|
|
- :data-source="dataSource"
|
|
|
- :render-sheet="renderSheet"
|
|
|
- @rendered="handleRendered"
|
|
|
- @click:bottom-bar="initMap"
|
|
|
- @error="handleExcelError"
|
|
|
- ></ExcelPage>
|
|
|
- </v-tab-item>
|
|
|
- </v-tabs-items>
|
|
|
+ <div v-if="fileType" style="height: 100%;">
|
|
|
+ <ParseData
|
|
|
+ v-if="!showSourcePreview"
|
|
|
+ :items="items"
|
|
|
+ :origin="origin"
|
|
|
+ :select="select"
|
|
|
+ @select="handleSelect"
|
|
|
+ @viewSource="handleViewSource"
|
|
|
+ ></ParseData>
|
|
|
+ <!-- 文件预览 -->
|
|
|
+ <SourceFilePreview
|
|
|
+ v-else
|
|
|
+ :file="file"
|
|
|
+ :file-type="fileType"
|
|
|
+ :file-url="itemData?.url"
|
|
|
+ @viewParsedData="handleViewParsedData"
|
|
|
+ ></SourceFilePreview>
|
|
|
+ </div>
|
|
|
+ <NonePage v-else />
|
|
|
</v-card>
|
|
|
|
|
|
<v-card class="db-box d-flex flex-column" elevation="5">
|
|
|
@@ -61,34 +53,6 @@
|
|
|
v-model="selectModel"
|
|
|
v-loading="loading"
|
|
|
>
|
|
|
- <template #head v-if="uploadTab === 1">
|
|
|
- <form-list ref="form" :items="formItems">
|
|
|
- <template #actions>
|
|
|
- <div style="width: 100%;" class="d-flex justify-space-between">
|
|
|
- <v-btn
|
|
|
- v-for="btn in controlBtn"
|
|
|
- :key="btn.text"
|
|
|
- rounded
|
|
|
- class="buttons ml-3"
|
|
|
- :color="btn.color"
|
|
|
- :disabled="btn.disabled && !file"
|
|
|
- @click="btn.handle(btn)"
|
|
|
- >
|
|
|
- <v-progress-circular
|
|
|
- v-if="btn.loading"
|
|
|
- indeterminate
|
|
|
- :size="18"
|
|
|
- width="2"
|
|
|
- color="white"
|
|
|
- class="mr-1"
|
|
|
- ></v-progress-circular>
|
|
|
- <v-icon left v-else>{{ btn.icon }}</v-icon>
|
|
|
- {{ btn.text }}
|
|
|
- </v-btn>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- </form-list>
|
|
|
- </template>
|
|
|
</edit-selected>
|
|
|
</v-tab-item>
|
|
|
<v-tab-item>
|
|
|
@@ -126,21 +90,21 @@
|
|
|
<script>
|
|
|
import EditSelected from './editSelected'
|
|
|
import UploadBtn from '@/components/UploadBtn'
|
|
|
-import FormList from '@/components/Form/list'
|
|
|
import EditBase from './editBase'
|
|
|
-import DDLPage from './ddl/index.vue'
|
|
|
-import ExcelPage from './excel/index.vue'
|
|
|
+import ParseData from './parseData.vue'
|
|
|
+import SourceFilePreview from './SourceFilePreview.vue'
|
|
|
+import NonePage from '@/components/Common/empty.vue'
|
|
|
+
|
|
|
import { api } from '@/api/dataGovernance'
|
|
|
-// import { handleReadFile } from '@/utils/file'
|
|
|
export default {
|
|
|
name: 'database-connect',
|
|
|
components: {
|
|
|
UploadBtn,
|
|
|
EditSelected,
|
|
|
EditBase,
|
|
|
- FormList,
|
|
|
- DDLPage,
|
|
|
- ExcelPage
|
|
|
+ ParseData,
|
|
|
+ SourceFilePreview,
|
|
|
+ NonePage
|
|
|
},
|
|
|
props: {
|
|
|
itemData: {
|
|
|
@@ -153,61 +117,22 @@ export default {
|
|
|
items: {},
|
|
|
origin: {},
|
|
|
tab: 0,
|
|
|
- uploadTab: 0,
|
|
|
names: {},
|
|
|
- fileName: undefined,
|
|
|
+ fileType: null,
|
|
|
loading: false,
|
|
|
loadingUpload: false,
|
|
|
- controlBtn: [
|
|
|
- {
|
|
|
- icon: 'mdi-swap-horizontal',
|
|
|
- key: 'analysis',
|
|
|
- color: 'primary',
|
|
|
- loading: false,
|
|
|
- disabled: false,
|
|
|
- text: '解析',
|
|
|
- handle: this.handleAnalysis
|
|
|
- }
|
|
|
- ],
|
|
|
select: null,
|
|
|
overlay: false,
|
|
|
- dataSource: null, // excel数据
|
|
|
selectModel: null,
|
|
|
- uploadBtnText: '导入DDL',
|
|
|
- isUpdateMap: true,
|
|
|
- renderSheet: true, // 自动渲染
|
|
|
file: null,
|
|
|
- formItems: {
|
|
|
- options: [
|
|
|
- {
|
|
|
- type: 'number',
|
|
|
- key: 'headRowNumber',
|
|
|
- value: 1,
|
|
|
- col: 4,
|
|
|
- label: '请输入表头所在行数 *',
|
|
|
- outlined: true,
|
|
|
- dense: true,
|
|
|
- rules: [v => v > 0 || '请输入表头所在行数']
|
|
|
- },
|
|
|
- {
|
|
|
- col: 8,
|
|
|
- slotName: 'actions'
|
|
|
- }
|
|
|
- ]
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
- computed: {
|
|
|
- uploadTabText () {
|
|
|
- return this.uploadTab === 0 ? '导入DDL' : this.uploadTab === 1 ? '导入Excel' : '导入文本'
|
|
|
+ showSourcePreview: false // 是否显示源文件预览
|
|
|
}
|
|
|
},
|
|
|
created () {
|
|
|
if (!Object.keys(this.itemData).length) {
|
|
|
return
|
|
|
}
|
|
|
- this.uploadTab = this.itemData.type === 'database' ? 0 : this.itemData.type === 'structure' ? 1 : 2
|
|
|
- this.uploadBtnText = this.uploadTabText
|
|
|
+ this.fileType = this.itemData.type
|
|
|
this.selectModel = this.itemData.parsed_data.map(e => {
|
|
|
return {
|
|
|
map: e,
|
|
|
@@ -229,100 +154,82 @@ export default {
|
|
|
async getFile (url) {
|
|
|
try {
|
|
|
const { data } = await api.downloadFile({ url })
|
|
|
- this.file = new File([data], url, { type: data.type || 'text/plain' })
|
|
|
- // await this.handleChangeFile(file)
|
|
|
+ // 从 URL 中提取文件名
|
|
|
+ const fileName = url.split('/').pop() || 'file'
|
|
|
+ // 根据文件类型设置 MIME 类型
|
|
|
+ const mimeTypes = {
|
|
|
+ pdf: 'application/pdf',
|
|
|
+ docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
|
+ xls: 'application/vnd.ms-excel',
|
|
|
+ xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
|
+ sql: 'text/plain'
|
|
|
+ // txt: 'text/plain'
|
|
|
+ }
|
|
|
+ const mimeType = mimeTypes[this.fileType] || 'application/octet-stream'
|
|
|
+ this.file = new File([data], fileName, { type: mimeType })
|
|
|
+
|
|
|
+ // 编辑需要展示解析数据时调用
|
|
|
+ // await this.handleChangeFile(this.file)
|
|
|
} catch (error) {
|
|
|
this.$snackbar.error(error)
|
|
|
}
|
|
|
},
|
|
|
- handleRendered () {
|
|
|
- this.showExcel = false
|
|
|
- if (!this.renderSheet) {
|
|
|
- return
|
|
|
- }
|
|
|
- // 渲染完毕
|
|
|
- this.initMap()
|
|
|
+ handleViewSource () {
|
|
|
+ this.showSourcePreview = true
|
|
|
},
|
|
|
- async initMap () {
|
|
|
- if (!this.isUpdateMap || !this.dataSource) {
|
|
|
+ handleViewParsedData () {
|
|
|
+ this.showSourcePreview = false
|
|
|
+ },
|
|
|
+ // 文件解析处理
|
|
|
+ async handleChangeFile (file) {
|
|
|
+ if (!file) {
|
|
|
return
|
|
|
}
|
|
|
- const row = this.formItems.options.find(e => e.key === 'headRowNumber').value
|
|
|
- const mapItems = this.$refs.excelPage?.getRow(row - 1)
|
|
|
- if (!mapItems || !mapItems.length) {
|
|
|
- this.selectModel = []
|
|
|
+
|
|
|
+ // 获取文件扩展名
|
|
|
+ const fileName = file.name || ''
|
|
|
+ const fileExt = fileName.split('.').pop()?.toLowerCase()
|
|
|
+
|
|
|
+ // 验证文件类型
|
|
|
+ const allowedTypes = ['sql', 'docx', 'xls', 'xlsx', 'pdf']
|
|
|
+ if (!fileExt || !allowedTypes.includes(fileExt)) {
|
|
|
+ this.$snackbar.warning('只支持上传 sql、docx、xls、xlsx、pdf 类型的文件')
|
|
|
return
|
|
|
}
|
|
|
- this.selectModel = mapItems.map(_e => {
|
|
|
- return {
|
|
|
- map: null,
|
|
|
- text: _e
|
|
|
- }
|
|
|
- })
|
|
|
- // 需解析excel内容,解析后接口返回元数据列表
|
|
|
- },
|
|
|
- handleTabChange (tab) {
|
|
|
- this.uploadTab = tab
|
|
|
- this.uploadBtnText = this.uploadTabText
|
|
|
- },
|
|
|
- // EXCEL文件解析
|
|
|
- async handleAnalysis (item) {
|
|
|
- item.loading = true
|
|
|
- await this.initMap()
|
|
|
- item.loading = false
|
|
|
- },
|
|
|
- // 文件解析处理
|
|
|
- async handleChangeFile (file) {
|
|
|
+
|
|
|
this.file = file
|
|
|
- if (this.uploadTab === 0) {
|
|
|
- // DDL 文件处理
|
|
|
- this.loadingUpload = true
|
|
|
- const query = new FormData()
|
|
|
- query.append('file', file)
|
|
|
- try {
|
|
|
- const { data } = await api.parseDDLFile(query)
|
|
|
- this.items = data.reduce((res, item) => {
|
|
|
- const { columns, exist, table_info: tableInfo } = item
|
|
|
- const key = tableInfo.name_zh || tableInfo.name_en
|
|
|
- res[key] = {
|
|
|
- exist,
|
|
|
- table_info: tableInfo,
|
|
|
- meta: columns.map(e => {
|
|
|
- return {
|
|
|
- text: e.name_zh,
|
|
|
- map: {
|
|
|
- ...e,
|
|
|
- data_standard: null
|
|
|
- }
|
|
|
+ this.fileType = fileExt
|
|
|
+
|
|
|
+ this.loadingUpload = true
|
|
|
+ const query = new FormData()
|
|
|
+ query.append('file', file)
|
|
|
+ try {
|
|
|
+ const { data } = await api.parseDDLFile(query)
|
|
|
+ this.items = data.reduce((res, item) => {
|
|
|
+ const { columns, exist, table_info: tableInfo } = item
|
|
|
+ const key = tableInfo.name_zh || tableInfo.name_en
|
|
|
+ res[key] = {
|
|
|
+ exist,
|
|
|
+ table_info: tableInfo,
|
|
|
+ meta: columns.map(e => {
|
|
|
+ return {
|
|
|
+ text: e.name_zh,
|
|
|
+ map: {
|
|
|
+ ...e,
|
|
|
+ data_standard: null
|
|
|
}
|
|
|
- })
|
|
|
- }
|
|
|
- return res
|
|
|
- }, {})
|
|
|
- this.origin = { ...this.items }
|
|
|
- } catch (error) {
|
|
|
- this.$snackbar.error(error)
|
|
|
- } finally {
|
|
|
- this.loadingUpload = false
|
|
|
- }
|
|
|
- } else if (this.uploadTab === 1) {
|
|
|
- // Excel 文件处理
|
|
|
- // const type = file.name.split('.').pop()
|
|
|
- // if (type !== 'xlsx' && type !== 'xls') {
|
|
|
- // this.$snackbar.error('请导入Excel文件')
|
|
|
- // return
|
|
|
- // }
|
|
|
- // this.fileName = file.name
|
|
|
- // this.renderSheet = true
|
|
|
- // handleReadFile(file, type, files => {
|
|
|
- // // 返回blob
|
|
|
- // this.dataSource = files
|
|
|
- // })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ return res
|
|
|
+ }, {})
|
|
|
+ this.origin = { ...this.items }
|
|
|
+ } catch (error) {
|
|
|
+ this.$snackbar.error(error)
|
|
|
+ } finally {
|
|
|
+ this.loadingUpload = false
|
|
|
}
|
|
|
},
|
|
|
- handleExcelError () {
|
|
|
- // Excel 加载错误处理
|
|
|
- },
|
|
|
// DDL使用该数据源
|
|
|
handleSelect (item, key) {
|
|
|
this.select = key
|
|
|
@@ -335,12 +242,11 @@ export default {
|
|
|
|
|
|
async handleSubmit () {
|
|
|
// DDL解析需要选择数据资源
|
|
|
- if (this.uploadTab === 0 && (!this.selectModel || !this.selectModel.length)) {
|
|
|
+ if (this.fileType === 'sql' && (!this.selectModel || !this.selectModel.length)) {
|
|
|
this.$snackbar.error('请先选择数据资源')
|
|
|
this.tab = 0
|
|
|
return
|
|
|
}
|
|
|
- const type = this.uploadTab === 0 ? 'database' : this.uploadTab === 1 ? 'structure' : 'unstructured'
|
|
|
try {
|
|
|
const obj = this.$refs.base.getValue()
|
|
|
if (!obj) {
|
|
|
@@ -349,7 +255,7 @@ export default {
|
|
|
|
|
|
const params = {
|
|
|
...obj,
|
|
|
- type
|
|
|
+ type: this.fileType
|
|
|
}
|
|
|
// 有id时,更新
|
|
|
if (this.itemData.id) {
|