diff --git a/api/app/lib/controllers/metadataAcquisition/dataSource.js b/api/app/lib/controllers/metadataAcquisition/dataSource.js
index bc740af..bd56972 100644
--- a/api/app/lib/controllers/metadataAcquisition/dataSource.js
+++ b/api/app/lib/controllers/metadataAcquisition/dataSource.js
@@ -6,11 +6,15 @@ function addDataSource(opts) {
const models = ctx.fs.dc.models;
try {
- const { name } = ctx.request.body
- const checkName = await models.DataSource.findOne({ where: { name, name } });
+ const { name, mountPath } = ctx.request.body
+ const checkName = await models.DataSource.findOne({ where: { name: name } });
+ const checkMountPath = await models.DataSource.findOne({ where: { mountPath: mountPath } });
if (checkName) {
ctx.status = 400;
ctx.body = { message: '该数据源名称已存在' }
+ } else if (checkMountPath) {
+ ctx.status = 400;
+ ctx.body = { message: '该资源路径已被使用' }
} else {
let rslt = ctx.request.body;
await models.DataSource.create(Object.assign({}, rslt))
diff --git a/api/app/lib/controllers/metadataAcquisition/taskHandle.js b/api/app/lib/controllers/metadataAcquisition/taskHandle.js
index b69b509..89810c8 100644
--- a/api/app/lib/controllers/metadataAcquisition/taskHandle.js
+++ b/api/app/lib/controllers/metadataAcquisition/taskHandle.js
@@ -46,8 +46,9 @@ async function handleTask(app, task) {
}//目录树下库只会存在一个 判断是否有库类型元数据 没有则新增库和表元数据 有库数据则比较更新表类型元数据 全量更新字段索引数据
})
let databaseId = databaseFind ? databaseFind.id : null;
+
+ const newTableNames = []
if (databaseFind) { //更新表类型元数据
- const newTableNames = []
Object.keys(tables).forEach(key => { newTableNames.push(key) });
//删除不存在表元数据
@@ -108,45 +109,74 @@ async function handleTask(app, task) {
}
})
- //字段/索引/外键全量更新 先删除之前的字段 再录入新的数据
- await models.MetadataDatabase.destroy({
+ //字段索引外键上一次存储集合
+ const tableChildrens = await models.MetadataDatabase.findAll({
where: {
type: { $in: ['字段', '索引', '外键'] },
catalog: dataSource.mountPath,
}
})
-
- const fieldBodys = []
- for (let table of metaDatabaseTables) {
- Object.keys(tables[table.name].structures).forEach(key => {
- dataToSave.parent = table.id;
- dataToSave.name = tables[table.name].structures[key].comment || key;
- dataToSave.code = key;
- dataToSave.type = '字段';
- const tableObj = { ...dataToSave }
- fieldBodys.push(tableObj)
+ let fieldBodys = []
+ let fieldRslt = null;
+ if (tableChildrens.length == 0) { //首次执行定时任务新增
+ for (let table of metaDatabaseTables) {
+ const children = handleAddTableChildren(dataToSave, tables, table);
+ fieldBodys = fieldBodys.concat(children)
+ }
+ fieldRslt = await models.MetadataDatabase.bulkCreate(fieldBodys);
+ } else {//更新数据
+ const deleteIds = [];//字段索引外键删除id集合
+ const deleteParentIds = [];//删除表集合
+ tableChildrens.forEach(s => {
+ let table = metaDatabaseTables.find(x => x.id == s.parent)
+ if (table) {
+ if (s.type == '字段' && !tables[table.name].structures[s.code]) {
+ deleteIds.push(s.id)
+ }
+ if (s.type == '外键' && !tables[table.name].foreignKeys.find(x => x.columnName == s.code)) {
+ deleteIds.push(s.id)
+ }
+ if (s.type == '索引' && !tables[table.name].indexes.find(x => x.name == s.code)) {
+ deleteIds.push(s.id)
+ }
+ } else {
+ if (!deleteParentIds.find(n => n == s.parent)) deleteParentIds.push(s.parent)
+ }
})
- tables[table.name].foreignKeys.forEach(v => {
- dataToSave.parent = table.id;
- dataToSave.name = v.columnName;
- dataToSave.code = v.columnName;
- dataToSave.type = '外键';
- const tableObj = { ...dataToSave }
- fieldBodys.push(tableObj)
+ //判断新增- 新增表 新增表字段
+ Object.keys(tables).forEach(key => {
+ const table = metaDatabaseTables.find(s => s.code == key)
+ if (tableChildrens.find(s => s.parent == table.id)) {
+ const children = handleAddTableChildren(dataToSave, tables, table, tableChildrens);
+ fieldBodys = fieldBodys.concat(children)
+ } else {
+ const children = handleAddTableChildren(dataToSave, tables, table);
+ fieldBodys = fieldBodys.concat(children)
+ }
})
- tables[table.name].indexes.forEach(v => {
- dataToSave.parent = table.id;
- dataToSave.name = v.name;
- dataToSave.code = v.name;
- dataToSave.type = '索引';
- const tableObj = { ...dataToSave }
- fieldBodys.push(tableObj)
+ //删除不存在的字段索引 外键
+ await models.MetadataDatabase.destroy({
+ where: {
+ type: { $in: ['字段', '索引', '外键'] },
+ catalog: dataSource.mountPath,
+ $or: [
+ { parent: { $in: deleteParentIds } },
+ { id: { $in: deleteIds } }
+ ]
+ }
})
+
+
+ //增加新增的字段索引外键
+ if (fieldBodys.length > 0) {
+ fieldRslt = await models.MetadataDatabase.bulkCreate(fieldBodys);
+ } else {
+ fieldRslt = true;
+ }
}
- const fieldRslt = await models.MetadataDatabase.bulkCreate(fieldBodys);
if (fieldRslt) {
const endTime = moment()
const logBody = {
@@ -168,10 +198,18 @@ async function handleTask(app, task) {
} catch (error) {
// await transaction.rollback();
const endTime = moment()
+ let message = error.message ? error.message : error
+ //空表auto-sequelize会抛出异常 提示信息处理
+ if (error.message && error.message.indexOf('No description found for') > -1) {
+ if (error.message.split('.') && error.message.split('.').length > 0) {
+ message = error.message.split('.')[0].split('"')[1] + '未定义任何字段'
+ }
+ }
+
const logBody = {
task: task.id,
success: false,
- details: '采集失败' + JSON.stringify(error).substring(0, 248),
+ details: '采集失败:' + JSON.stringify(message).substring(0, 247),
startTime: startTime,
endTime: endTime
}
@@ -181,12 +219,52 @@ async function handleTask(app, task) {
if (task.retried && task.retryCount && task.retryTime && taskRetryIndex[task.id] < task.retryCount) {
setTimeout(() => {
handleTask(app, task)
- }, 1000 * 60 * task.retryCount);
+ }, 1000 * 60 * task.retryTime);
}
app.fs.logger.error(`sechedule: handleTask, error: ${error}`);
}
}
+//处理字段 索引 外键 新增body
+function handleAddTableChildren(dataToSave, tables, table, tableChildrens) {
+ const fieldBodys = [];
+ Object.keys(tables[table.name].structures).forEach(key => {
+ if (!tableChildrens || !tableChildrens.find(s => s.code == key)) {
+ dataToSave.parent = table.id;
+ dataToSave.name = tables[table.name].structures[key].comment || key;
+ dataToSave.code = key;
+ dataToSave.type = '字段';
+ const tableObj = { ...dataToSave }
+ fieldBodys.push(tableObj)
+ }
+ })
+
+ tables[table.name].foreignKeys.forEach(v => {
+ if (!tableChildrens || !tableChildrens.find(s => s.code == v.columnName)) {
+ dataToSave.parent = table.id;
+ dataToSave.name = v.columnName;
+ dataToSave.code = v.columnName;
+ dataToSave.type = '外键';
+ const tableObj = { ...dataToSave }
+ fieldBodys.push(tableObj)
+ }
+
+ })
+
+ tables[table.name].indexes.forEach(v => {
+ if (!tableChildrens || !tableChildrens.find(s => s.code == v.name)) {
+ dataToSave.parent = table.id;
+ dataToSave.name = v.name;
+ dataToSave.code = v.name;
+ dataToSave.type = '索引';
+ const tableObj = { ...dataToSave }
+ fieldBodys.push(tableObj)
+ }
+ })
+
+ return fieldBodys;
+}
+
function createDbOptions(params) {
const dbOptions = {
database: params.database,
diff --git a/web/client/src/layout/components/sider/index.js b/web/client/src/layout/components/sider/index.js
index 3c1e6b2..e0ccbb0 100644
--- a/web/client/src/layout/components/sider/index.js
+++ b/web/client/src/layout/components/sider/index.js
@@ -3,6 +3,7 @@ import { Menu } from 'antd';
const JumpUrls = [
{ url: '/risk/hiddenrectification_approval', keys: 'riskHiddenrectification_approval' },
{ url: '/safetymanage/hiddenrectification_approval', keys: 'hiddenrectification_approval' },
+ { url: '/metadataManagement/latestMetadata', keys: 'latestMetadata' },
]
const Sider = (props) => {
const [items, setItems] = useState([])
diff --git a/web/client/src/sections/metadataAcquisition/components/steps/postgre/stepOne.js b/web/client/src/sections/metadataAcquisition/components/steps/postgre/stepOne.js
index a3fb950..2f114d6 100644
--- a/web/client/src/sections/metadataAcquisition/components/steps/postgre/stepOne.js
+++ b/web/client/src/sections/metadataAcquisition/components/steps/postgre/stepOne.js
@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react'
-import { Button, Form, Input, Row, Col } from 'antd';
+import { Button, Spin, Input, Row, Col } from 'antd';
import {
ProForm,
ProFormSelect,
@@ -7,10 +7,11 @@ import {
ProFormText,
ProFormTreeSelect
} from '@ant-design/pro-form';
+import { push } from 'react-router-redux';
import '../../style.less';
function StepOne(props) {
- const { next, stepOneValues, stepOneValuesFinish, readOnly, treeData, dataSources } = props;
+ const { next, stepOneValues, stepOneValuesFinish, readOnly, treeData, dataSources, dispatch, refresh, loading, editData } = props;
const formRef = React.createRef();
const initialValues = stepOneValues ? stepOneValues : {
adapterName: 'PostgreSQL采集适配器',
@@ -19,7 +20,7 @@ function StepOne(props) {
// mountPath: 1,
}
- const formItemLayout = { labelCol: { span: 3 }, wrapperCol: { span: 10 } };
+ const formItemLayout = { labelCol: { span: 3 }, wrapperCol: { span: 12 } };
const getTreeNodeData = (dataSource, parent, key) => {
let treeData = [];
@@ -40,8 +41,8 @@ function StepOne(props) {
}
return treeData
}
- const treeDataFilter = treeData ? getTreeNodeData(treeData, null, 'rc') : []
- return <>
+ const treeDataFilter = treeData && dataSources?.rows?.length > 0 ? getTreeNodeData(treeData, null, 'rc') : []
+ return
*/}
- 0 ? {
return treeDataFilter || [];
@@ -137,7 +139,23 @@ function StepOne(props) {
label: 'title',
},
}}
- />
+ addonAfter={!editData && <>
+ {
+ dispatch(push(`/metadataManagement/latestMetadata`));
+ }} style={{ marginRight: 8 }}>新建
+ {
+ refresh()
+ }}>刷新
+ >}
+ disabled={editData}
+ /> : }
- >
+
}
export default StepOne
\ No newline at end of file
diff --git a/web/client/src/sections/metadataAcquisition/components/steps/postgre/stepThree.js b/web/client/src/sections/metadataAcquisition/components/steps/postgre/stepThree.js
index 7bc86e7..d1bb9ad 100644
--- a/web/client/src/sections/metadataAcquisition/components/steps/postgre/stepThree.js
+++ b/web/client/src/sections/metadataAcquisition/components/steps/postgre/stepThree.js
@@ -114,7 +114,7 @@ function StepThree(props) {
{
const query = {
- limit: search ? 10 : pageSize || 10,
- page: search ? 1 : currentPage || 1,
+ // limit: search ? 10 : pageSize || 10,
+ // page: search ? 1 : currentPage || 1,
name: searchValue
}
dispatch(actions.metadataAcquisition.getDataSources(query));
}
- const { data: treeData = [] } = useFsRequest({ url: ApiTable.getResourceCatalog });
+ const { data: treeData = [] } = useFsRequest({
+ url: ApiTable.getResourceCatalog,
+ refreshDeps: [refreshTree]
+ });
useEffect(() => {
dispatch(actions.metadataAcquisition.getAdapters())
@@ -141,6 +145,10 @@ function DataSourceManagement(props) {
}
}
}
+ const refresh = () => {
+ queryData();
+ setRefreshTree(refreshTree + 1)
+ }
return
@@ -168,8 +176,9 @@ function DataSourceManagement(props) {
total: dataSources?.count,
showSizeChanger: true,
// showQuickJumper: true,
- current: currentPage,
- pageSize: pageSize || 10,
+ // current: currentPage,
+ // pageSize: pageSize || 10,
+ defaultPageSize: 10,
pageSizeOptions: [10, 20, 50],
showTotal: (total) => {
return {`共${Math.ceil(total / pageSize)}页,${total}项`}
@@ -201,6 +210,7 @@ function DataSourceManagement(props) {
visible={visible}
onFinish={onFinish}
treeData={treeData}
+ refresh={refresh}
{...props}
/>
}