diff --git a/api/app/lib/controllers/latestMetadata/index.js b/api/app/lib/controllers/latestMetadata/index.js
index b45ba42..87a881a 100644
--- a/api/app/lib/controllers/latestMetadata/index.js
+++ b/api/app/lib/controllers/latestMetadata/index.js
@@ -77,6 +77,7 @@ async function delResourceCatalog(ctx) {
const { id } = ctx.params;
let resourceCatalogInfo = await models.ResourceCatalog.findOne({ where: { id } });
if (resourceCatalogInfo) {
+ let deletable = true;
let childResourceCatalogInfo = await models.ResourceCatalog.findOne({ where: { parent: id } });
let databaseInfo = await models.MetadataDatabase.findOne({ where: { catalog: id } });
let fileInfo = await models.MetadataFile.findOne({ where: { catalog: id } });
@@ -86,16 +87,15 @@ async function delResourceCatalog(ctx) {
ctx.body = { message: '存在关联子类目录或元数据,请删除相关数据,再删除该资源目录' }
deletable = false;
}
- }
- if (deletable) {
- await models.ResourceCatalog.destroy({
- where: { id: id },
- transaction
- })
- await transaction.commit();
- ctx.status = 200;
- ctx.body = { message: '删除资源目录成功' }
-
+ if (deletable) {
+ await models.ResourceCatalog.destroy({
+ where: { id: id },
+ transaction
+ })
+ await transaction.commit();
+ ctx.status = 200;
+ ctx.body = { message: '删除资源目录成功' }
+ }
} else {
ctx.status = 400;
ctx.body = { message: '该资源目录不存在' }
diff --git a/web/client/src/sections/metadataManagement/actions/index.js b/web/client/src/sections/metadataManagement/actions/index.js
index 3517c90..9f06f2a 100644
--- a/web/client/src/sections/metadataManagement/actions/index.js
+++ b/web/client/src/sections/metadataManagement/actions/index.js
@@ -3,9 +3,11 @@
import * as example from './example'
import * as tags from './tags'
import * as models from './model'
+import * as metadata from './metadata'
export default {
...example,
...tags,
- ...models
+ ...models,
+ ...metadata
}
\ No newline at end of file
diff --git a/web/client/src/sections/metadataManagement/actions/metadata.js b/web/client/src/sections/metadataManagement/actions/metadata.js
new file mode 100644
index 0000000..bafacd9
--- /dev/null
+++ b/web/client/src/sections/metadataManagement/actions/metadata.js
@@ -0,0 +1,53 @@
+'use strict';
+
+import { basicAction } from '@peace/utils'
+import { ApiTable } from '$utils'
+
+export function getResourceCatalog(params) {
+ return dispatch => basicAction({
+ type: 'get',
+ dispatch: dispatch,
+ query: params,
+ actionType: 'GET_RESOURCE_CATALOG',
+ url: ApiTable.getResourceCatalog,
+ msg: { error: '获取资源目录失败' },
+ reducer: { name: 'resourceCatalog' }
+ });
+}
+
+export function postResourceCatalog(data) {
+ return dispatch => basicAction({
+ type: 'post',
+ data: data,
+ dispatch: dispatch,
+ actionType: 'POST_RESOURCE_CATALOG',
+ url: ApiTable.postResourceCatalog,
+ msg: { option: '新增资源目录' },
+ reducer: {}
+ });
+}
+
+export function putResourceCatalog(id, data) {
+ return dispatch => basicAction({
+ type: 'put',
+ data: data,
+ dispatch,
+ actionType: 'PUT_RESOURCE_CATALOG',
+ url: ApiTable.putResourceCatalog.replace('{id}', id),
+ msg: {
+ option: '修改资源目录',
+ }
+ });
+}
+
+export function delResourceCatalog(id) {
+ return dispatch => basicAction({
+ type: 'del',
+ dispatch,
+ actionType: 'DELETE_RESOURCE_CATALOG',
+ url: ApiTable.delResourceCatalog.replace('{id}', id),
+ msg: {
+ option: '删除资源目录',
+ }
+ });
+}
\ No newline at end of file
diff --git a/web/client/src/sections/metadataManagement/components/resourceCatalogModal.js b/web/client/src/sections/metadataManagement/components/resourceCatalogModal.js
new file mode 100644
index 0000000..9431d6e
--- /dev/null
+++ b/web/client/src/sections/metadataManagement/components/resourceCatalogModal.js
@@ -0,0 +1,86 @@
+import React, { useEffect, useState } from 'react';
+import { Modal, Input, Form, message } from 'antd';
+const { TextArea } = Input;
+const ResourceCatalogModal = (props) => {
+ const { resourceCatalog, onConfirm, onCancel, editData } = props;
+ const [form] = Form.useForm();
+ useEffect(() => {
+ }, []);
+ const handleOk = () => {
+ form.validateFields().then(values => {
+ if (onConfirm) {
+ if (editData.add) {
+ //新建
+ let exist = resourceCatalog.find(rc => rc.name === values.name);
+ if (exist) {
+ message.error('该资源目录名称已存在');
+ return false;
+ }
+ exist = resourceCatalog.find(rc => rc.code === values.code);
+ if (exist) {
+ message.error('该资源目录代码已存在');
+ return false;
+ }
+ } else {//修改
+ let exist = resourceCatalog.find(rc => rc.name === values.name && rc.id != editData.record.id);
+ if (exist) {
+ message.error('该资源目录名称已存在');
+ return false;
+ }
+ exist = resourceCatalog.find(rc => rc.code === values.code && rc.id != editData.record.id);
+ if (exist) {
+ message.error('该资源目录代码已存在');
+ return false;
+ }
+ }
+ onConfirm(values)
+ }
+ })
+ }
+ const validatorNull = (rule, value, getFieldValue, validateFields) => {
+ if (!value || !value.trim().length) {
+ return Promise.reject(new Error(`${rule.field === 'name' ? '名称' : '代码'}不可空字符串`));
+ }
+ return Promise.resolve();
+ }
+ return (
+ handleOk(null)}
+ onCancel={onCancel}>
+
+
+ : null}
+ ({
+ validator(_, value) { return validatorNull(_, value, getFieldValue, validateFields) }
+ })]}>
+
+
+ ({
+ validator(_, value) { return validatorNull(_, value, getFieldValue, validateFields) }
+ })]}>
+
+
+
+
+
+
+
+ )
+}
+export default ResourceCatalogModal;
\ No newline at end of file
diff --git a/web/client/src/sections/metadataManagement/containers/latestMetadata.js b/web/client/src/sections/metadataManagement/containers/latestMetadata.js
index ebdba2d..4f9a791 100644
--- a/web/client/src/sections/metadataManagement/containers/latestMetadata.js
+++ b/web/client/src/sections/metadataManagement/containers/latestMetadata.js
@@ -1,24 +1,160 @@
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
-import { Button, } from 'antd'
+import { Spin, Row, Col, Tree, Button, Tooltip, Popconfirm } from 'antd';
+import { PlusCircleOutlined, EditOutlined, MinusCircleOutlined } from '@ant-design/icons';
+import theStyle from './style.css';
+import ResourceCatalogModal from '../components/resourceCatalogModal';
+let expandedKeysData = [];
const LatestMetadata = (props) => {
- const { user, dispatch, actions, history } = props;
+ const { user, dispatch, actions, clientHeight, resourceCatalog, isRequesting } = props;
+ const { metadataManagement } = actions;
+ const [resourceCatalogData, setResourceCatalogData] = useState([]);
+ const [selectedKeys, setSelectedKeys] = useState([]);
+ const [expandedKeys, setExpandedKeys] = useState([]);
+ const [modalVisible, setModalVisible] = useState(false);
+ const [editData, setEditData] = useState({});
useEffect(() => {
+ initData(true);
}, [])
+ const initData = (configRefresh) => {
+ dispatch(metadataManagement.getResourceCatalog()).then(res => {
+ const { data } = res.payload;
+ if (res.success) {
+ const resourceCatalogData = getTreeNodeData(data, null, 'rc');
+ setResourceCatalogData(resourceCatalogData);
+ if (data.length) {
+ if (configRefresh) {
+ setExpandedKeys(expandedKeysData);
+ setSelectedKeys(expandedKeysData);
+ }
+ } else {
+ setExpandedKeys([]);
+ setSelectedKeys([]);
+ };
+ }
+ })
+ }
+ const getTreeNodeData = (dataSource, parent, key) => {
+ let treeData = [];
+ let data = [];
+ if (!parent) {
+ data = dataSource.filter(ds => !ds.parent);
+ if (!expandedKeysData.length && data.length) {
+ expandedKeysData.push(`rc-${data[0].id}`);
+ }
+ } else {
+ data = dataSource.filter(ds => ds.parent == parent);
+ }
+ treeData = data.map(ds => {
+ return { title: renderTreeNode(ds, dataSource), key: `${key}-${ds.id}`, id: ds.id }
+ });
+ for (let d of treeData) {
+ d.children = getTreeNodeData(dataSource, d.id, d.key);
+ }
+ return treeData
+ }
- return <>最新元数据
-
- >
-}
+ const setTreeNodeTitle = (name) => {
+ let content = {name}
+ if (name.length > 10) {
+ content =
+ {name.substring(0, 10) + '...'}
+
+ }
+ return content;
+ }
+
+ const renderTreeNode = (ds, dataSource) => {
+ return
+ {setTreeNodeTitle(ds.name)}
+
{
+ let record = JSON.parse(JSON.stringify(ds));
+ let parentData = dataSource.filter(rc => rc.id === record.parent);
+ record.parentName = parentData.length ? parentData[0].name : '';
+ setEditData({ record: record, title: '修改子类', child: ds.parent ? true : false, });
+ setModalVisible(true);
+ }} />
+ {
+ dispatch(metadataManagement.delResourceCatalog(ds.id)).then((res) => {
+ if (res.success) {
+ expandedKeysData = []; initData(true);
+ }
+ setModalVisible(false);
+ });
+ }} okText="确定" cancelText="取消">
+
+
+ {
+ setEditData({ record: { parent: ds.id, parentName: ds.name }, title: '新建子类', child: true, add: true });
+ setModalVisible(true);
+ }} />
+
+ };
+ //新建、修改
+ const onConfirm = (values) => {
+ let obj = { ...values }
+ if (editData.add) {
+ obj = { ...values, ...editData.record || {} }
+ dispatch(metadataManagement.postResourceCatalog(obj)).then(() => {
+ initData(); setModalVisible(false);
+ });
+ } else {
+ dispatch(metadataManagement.putResourceCatalog(editData.record.id, obj)).then(() => {
+ initData(); setModalVisible(false);
+ });
+ }
+ }
+ return
+
+
+
+ {
+ if (e.selected) {
+ // setCurrentPage(1);
+ setSelectedKeys(keys);
+ // let keyArr = allTreeNodeKeys.filter(ak => ak.key.includes(keys[0]));
+ // let ids = keyArr.map(key => key.id);
+ // console.log('all-' + JSON.stringify(ids))
+ }
+ }}
+ onExpand={(keys) => {
+ setExpandedKeys(keys);
+ }}
+ treeData={resourceCatalogData}
+ />
+
+
+
+
+ {
+ modalVisible ?
+ setModalVisible(false)}
+ onConfirm={onConfirm} /> : ''
+ }
+
+}
function mapStateToProps(state) {
- const { global, auth } = state;
+ const { global, auth, resourceCatalog } = state;
return {
- clientHeight: global.clientHeight,
user: auth.user,
actions: global.actions,
+ clientHeight: global.clientHeight,
+ resourceCatalog: resourceCatalog?.data || [],
+ isRequesting: resourceCatalog.isRequesting
};
}
export default connect(mapStateToProps)(LatestMetadata)
\ No newline at end of file
diff --git a/web/client/src/sections/metadataManagement/containers/style.css b/web/client/src/sections/metadataManagement/containers/style.css
new file mode 100644
index 0000000..2f1b511
--- /dev/null
+++ b/web/client/src/sections/metadataManagement/containers/style.css
@@ -0,0 +1,16 @@
+.icon .tip {
+ margin-left: 10px;
+ -webkit-transition: opacity 0.1s 0.2s;
+ opacity: 0;
+ pointer-events: none;
+}
+
+.icon:hover .tip {
+ -webkit-transition: opacity 0.2s;
+ opacity: 1;
+ pointer-events: auto;
+}
+
+.icon .tip:hover {
+ -webkit-transition: none;
+}
\ No newline at end of file
diff --git a/web/client/src/sections/metadataManagement/containers/tagManagement.js b/web/client/src/sections/metadataManagement/containers/tagManagement.js
index 3fe187c..c903174 100644
--- a/web/client/src/sections/metadataManagement/containers/tagManagement.js
+++ b/web/client/src/sections/metadataManagement/containers/tagManagement.js
@@ -16,17 +16,17 @@ const TagManagement = (props) => {
const [editData, setEditData] = useState({ title: '', lable: '', setTagSet: null })
useEffect(() => {
- initData();
+ initData(true);
}, [])
const initData = (configRefresh) => {
dispatch(metadataManagement.getTagList()).then(res => {
const { data } = res.payload;
if (res.success) {
- if (configRefresh)
+ if (!configRefresh)
setModalVisible(false);
setTagData(data);
if (data.length) {
- if (!configRefresh)
+ if (configRefresh)
setActiveKey(`tagSet-${data[0].tagSetId}`)
} else setActiveKey('');
}
@@ -96,20 +96,20 @@ const TagManagement = (props) => {
if (editData.setEditData) {//标签集
if (editData.name)//修改
dispatch(metadataManagement.putTagSets(editData.id, { ...values })).then(() => {
- initData(true);
+ initData();
});
else//新建
dispatch(metadataManagement.postTagSets({ ...values })).then(() => {
- initData(true);
+ initData();
});
} else {
if (editData.name)//修改
dispatch(metadataManagement.putTags(editData.id, { ...values })).then(() => {
- initData(true);
+ initData();
});
else//新建
dispatch(metadataManagement.postTags({ tagSetId: editData.tagSetId, ...values })).then(() => {
- initData(true);
+ initData();
});
}
}
diff --git a/web/client/src/sections/metadataManagement/routes.js b/web/client/src/sections/metadataManagement/routes.js
index 063e29e..44457a8 100644
--- a/web/client/src/sections/metadataManagement/routes.js
+++ b/web/client/src/sections/metadataManagement/routes.js
@@ -14,7 +14,7 @@ export default [{
breadcrumb: '最新元数据',
childRoutes: [{
path: '/detail/:id',
- key: 'detail',
+ key: 'metadataDetail',
component: MetadataDetails,
breadcrumb: '元数据详情'
}]
diff --git a/web/client/src/utils/webapi.js b/web/client/src/utils/webapi.js
index 2aa7118..9c14977 100644
--- a/web/client/src/utils/webapi.js
+++ b/web/client/src/utils/webapi.js
@@ -17,6 +17,11 @@ export const ApiTable = {
getMetaModelList: 'meta/models',
addMetaModel: 'meta/model',
modifyMetaModel: 'meta/model/{id}',
+ //最新元数据-资源目录
+ getResourceCatalog: 'resource-catalog',
+ postResourceCatalog: 'resource-catalog',
+ putResourceCatalog: 'resource-catalog/{id}',
+ delResourceCatalog: 'resource-catalog/{id}',
//元数据采集
pgCheckConnect: 'adapter/check/connect',