Browse Source

库表元数据 打标新增更新、资源申请功能

master
zmh 2 years ago
parent
commit
343ea5dab9
  1. 162
      api/app/lib/controllers/latestMetadata/index.js
  2. 30
      api/app/lib/routes/latestMetadata/index.js
  3. 47
      web/client/src/sections/metadataManagement/actions/metadata.js
  4. 4
      web/client/src/sections/metadataManagement/components/metadataDatabaseModal.js
  5. 53
      web/client/src/sections/metadataManagement/components/metadataResourceModal.js
  6. 79
      web/client/src/sections/metadataManagement/components/metadataTagModal.js
  7. 87
      web/client/src/sections/metadataManagement/containers/databasesTable.js
  8. 2
      web/client/src/sections/metadataManagement/containers/metadataDetails.js
  9. 14
      web/client/src/utils/webapi.js

162
api/app/lib/controllers/latestMetadata/index.js

@ -30,11 +30,16 @@ async function postResourceCatalog(ctx) {
if (postOne) { if (postOne) {
ctx.status = 400; ctx.status = 400;
ctx.body = { message: '该资源目录名称或代码已存在' } ctx.body = { message: '该资源目录名称或代码已存在' }
} else {
if (!name || !code) {
ctx.body = { message: '参数不全,请重新配置' }
ctx.status = 400;
} else { } else {
await models.ResourceCatalog.create(ctx.request.body); await models.ResourceCatalog.create(ctx.request.body);
ctx.body = { message: '新建资源目录成功' } ctx.body = { message: '新建资源目录成功' }
ctx.status = 200; ctx.status = 200;
} }
}
} catch (error) { } catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400; ctx.status = 400;
@ -260,7 +265,7 @@ async function getMetadataModels(ctx) {
} }
//新建库表元数据 //新建库表元数据
async function postMeatadataDatabases(ctx) { async function postMetadataDatabases(ctx) {
try { try {
const { name, code, catalog } = ctx.request.body; const { name, code, catalog } = ctx.request.body;
const models = ctx.fs.dc.models; const models = ctx.fs.dc.models;
@ -270,11 +275,16 @@ async function postMeatadataDatabases(ctx) {
if (postOne) { if (postOne) {
ctx.status = 400; ctx.status = 400;
ctx.body = { message: '该资源目录下元数据名称或代码已存在' } ctx.body = { message: '该资源目录下元数据名称或代码已存在' }
} else {
if (!name || !code || !catalog) {
ctx.body = { message: '参数不全,请重新配置' }
ctx.status = 400;
} else { } else {
await models.MetadataDatabase.create({ createAt: moment(), ...ctx.request.body }); await models.MetadataDatabase.create({ createAt: moment(), ...ctx.request.body });
ctx.body = { message: '新建元数据成功' } ctx.body = { message: '新建元数据成功' }
ctx.status = 200; ctx.status = 200;
} }
}
} catch (error) { } catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400; ctx.status = 400;
@ -285,7 +295,7 @@ async function postMeatadataDatabases(ctx) {
} }
//修改库表元数据 //修改库表元数据
async function putMeatadataDatabases(ctx) { async function putMetadataDatabases(ctx) {
try { try {
const { id } = ctx.params; const { id } = ctx.params;
const { catalog, name, code } = ctx.request.body; const { catalog, name, code } = ctx.request.body;
@ -314,7 +324,7 @@ async function putMeatadataDatabases(ctx) {
} }
} }
//删除库表元数据 //删除库表元数据
async function delMeatadataDatabases(ctx) { async function delMetadataDatabases(ctx) {
const transaction = await ctx.fs.dc.orm.transaction(); const transaction = await ctx.fs.dc.orm.transaction();
try { try {
const models = ctx.fs.dc.models; const models = ctx.fs.dc.models;
@ -397,6 +407,140 @@ async function getMetadataDatabasesById(ctx) {
} }
} }
} }
//打标元数据
async function postTagMetadata(ctx) {
const transaction = await ctx.fs.dc.orm.transaction();
try {
const { tags, database, file, restapi } = ctx.request.body;
const models = ctx.fs.dc.models;
if (tags.length && (database || file || restapi)) {
if (database) {
await models.TagDatabase.destroy({ where: { database: database }, transaction });
const data = tags.map(tag => { return { tagId: tag, database: database } });
if (data.length)
await models.TagDatabase.bulkCreate(data, { transaction });
}
if (file) {
await models.TagFile.destroy({ where: { file: file }, transaction });
const data = tags.map(tag => { return { tagId: tag, file: file } });
if (data.length)
await models.TagFile.bulkCreate(data, { transaction });
}
if (restapi) {
await models.TagRestapi.destroy({ where: { restapi: restapi }, transaction });
const data = tags.map(tag => { return { tagId: tag, restapi: restapi } });
if (data.length)
await models.TagRestapi.bulkCreate(data, { transaction });
}
await transaction.commit();
ctx.status = 204;
} else {
ctx.body = { message: '参数不全,请重新配置' }
ctx.status = 400;
}
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "打标元数据失败"
}
}
}
//获取元数据已打标数据
async function getTagMetadata(ctx) {
try {
const models = ctx.fs.dc.models;
const { id } = ctx.params;
const { type } = ctx.query;
let rslt = [];
if (type === 'database') {
rslt = await models.Tag.findAll({
where: { '$tagDatabases.database$': id },
include: [{
model: models.TagDatabase,
}],
order: [['id', 'asc']],
});
}
if (type === 'file') {
rslt = await models.Tag.findAll({
where: { '$tagFiles.file$': id },
include: [{
model: models.TagFile,
}],
order: [['id', 'asc']],
});
}
if (type === 'restapi') {
rslt = await models.Tag.findAll({
where: { '$tagRestapis.restapi$': id },
include: [{
model: models.TagRestapi,
}],
order: [['id', 'asc']],
});
}
ctx.status = 200;
ctx.body = rslt;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "获取元数据已打标数据失败"
}
}
}
//申请资源
async function postMetadataResourceApplications(ctx) {
try {
const { resourceName, applyBy } = ctx.request.body;
if (!resourceName || !applyBy) {
ctx.status = 400;
ctx.body = { message: '参数不全,请重新申请资源' }
} else {
const models = ctx.fs.dc.models;
const postOne = await models.ResourceConsumption.findOne({
where: { applyBy: applyBy, resourceName: resourceName }
});
if (postOne) {
ctx.status = 400;
ctx.body = { message: '该用户已申请过该元数据资源' }
} else {
await models.ResourceConsumption.create({ applyAt: moment(), approveState: '审批中', ...ctx.request.body });
ctx.body = { message: '申请资源成功' }
ctx.status = 200;
}
}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "申请资源失败"
}
}
}
//获取元数据资源申请记录
async function getMetadataResourceApplications(ctx) {
try {
const models = ctx.fs.dc.models;
const { resourceNames, type } = ctx.query;
const rslt = await models.ResourceConsumption.findAll({
where: { resourceName: { $in: resourceNames.split(',') }, resourceType: type }
});
ctx.status = 200;
ctx.body = rslt;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "获取元数据资源申请记录失败"
}
}
}
module.exports = { module.exports = {
getResourceCatalog, getResourceCatalog,
postResourceCatalog, postResourceCatalog,
@ -406,8 +550,12 @@ module.exports = {
getMetadataFiles, getMetadataFiles,
getMetadataRestapis, getMetadataRestapis,
getMetadataModels, getMetadataModels,
postMeatadataDatabases, postMetadataDatabases,
putMeatadataDatabases, putMetadataDatabases,
delMeatadataDatabases, delMetadataDatabases,
getMetadataDatabasesById getMetadataDatabasesById,
postTagMetadata,
getTagMetadata,
postMetadataResourceApplications,
getMetadataResourceApplications
} }

30
api/app/lib/routes/latestMetadata/index.js

@ -6,13 +6,13 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/resource-catalog'] = { content: '获取资源目录', visible: false }; app.fs.api.logAttr['GET/resource-catalog'] = { content: '获取资源目录', visible: false };
router.get('/resource-catalog', latestMetadata.getResourceCatalog); router.get('/resource-catalog', latestMetadata.getResourceCatalog);
app.fs.api.logAttr['POST /resource-catalog'] = { content: '新建资源目录', visible: true }; app.fs.api.logAttr['POST/resource-catalog'] = { content: '新建资源目录', visible: true };
router.post('/resource-catalog', latestMetadata.postResourceCatalog); router.post('/resource-catalog', latestMetadata.postResourceCatalog);
app.fs.api.logAttr['PUT /resource-catalog/:id'] = { content: '修改资源目录', visible: true }; app.fs.api.logAttr['PUT/resource-catalog/:id'] = { content: '修改资源目录', visible: true };
router.put('/resource-catalog/:id', latestMetadata.putResourceCatalog); router.put('/resource-catalog/:id', latestMetadata.putResourceCatalog);
app.fs.api.logAttr['DEL /resource-catalog/:id'] = { content: '删除资源目录', visible: true }; app.fs.api.logAttr['DEL/resource-catalog/:id'] = { content: '删除资源目录', visible: true };
router.delete('/resource-catalog/:id', latestMetadata.delResourceCatalog); router.delete('/resource-catalog/:id', latestMetadata.delResourceCatalog);
app.fs.api.logAttr['GET/metadata/databases'] = { content: '获取库表元数据列表', visible: false }; app.fs.api.logAttr['GET/metadata/databases'] = { content: '获取库表元数据列表', visible: false };
@ -27,15 +27,27 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/metadata/models'] = { content: '获取元数据模型', visible: false }; app.fs.api.logAttr['GET/metadata/models'] = { content: '获取元数据模型', visible: false };
router.get('/metadata/models', latestMetadata.getMetadataModels); router.get('/metadata/models', latestMetadata.getMetadataModels);
app.fs.api.logAttr['POST /meatadata/databases'] = { content: '新建库表元数据', visible: true }; app.fs.api.logAttr['POST/metadata/databases'] = { content: '新建库表元数据', visible: true };
router.post('/meatadata/databases', latestMetadata.postMeatadataDatabases); router.post('/metadata/databases', latestMetadata.postMetadataDatabases);
app.fs.api.logAttr['PUT /meatadata/databases/:id'] = { content: '修改库表元数据', visible: true }; app.fs.api.logAttr['PUT/metadata/databases/:id'] = { content: '修改库表元数据', visible: true };
router.put('/meatadata/databases/:id', latestMetadata.putMeatadataDatabases); router.put('/metadata/databases/:id', latestMetadata.putMetadataDatabases);
app.fs.api.logAttr['DEL /meatadata/databases/:id'] = { content: '删除库表元数据', visible: true }; app.fs.api.logAttr['DEL/metadata/databases/:id'] = { content: '删除库表元数据', visible: true };
router.delete('/meatadata/databases/:id', latestMetadata.delMeatadataDatabases); router.delete('/metadata/databases/:id', latestMetadata.delMetadataDatabases);
app.fs.api.logAttr['GET/metadata/databases/:id'] = { content: '获取库表元数据基本信息', visible: false }; app.fs.api.logAttr['GET/metadata/databases/:id'] = { content: '获取库表元数据基本信息', visible: false };
router.get('/metadata/databases/:id', latestMetadata.getMetadataDatabasesById); router.get('/metadata/databases/:id', latestMetadata.getMetadataDatabasesById);
app.fs.api.logAttr['POST/tag/metadata'] = { content: '打标元数据', visible: true };
router.post('/tag/metadata', latestMetadata.postTagMetadata);
app.fs.api.logAttr['GET/tag/metadata/:id'] = { content: '获取元数据已打标数据', visible: true };
router.get('/tag/metadata/:id', latestMetadata.getTagMetadata);
app.fs.api.logAttr['POST/resource-consumption/applications'] = { content: '申请资源', visible: true };
router.post('/resource-consumption/applications', latestMetadata.postMetadataResourceApplications);
app.fs.api.logAttr['GET/resource-consumption/applications'] = { content: '获取元数据资源申请记录', visible: true };
router.get('/resource-consumption/applications', latestMetadata.getMetadataResourceApplications);
}; };

47
web/client/src/sections/metadataManagement/actions/metadata.js

@ -100,37 +100,37 @@ export function getMetadataModels(params) {
}); });
} }
export function postMeatadataDatabases(data) { export function postMetadataDatabases(data) {
return dispatch => basicAction({ return dispatch => basicAction({
type: 'post', type: 'post',
data: data, data: data,
dispatch: dispatch, dispatch: dispatch,
actionType: 'POST_METADATA_DATABASES', actionType: 'POST_METADATA_DATABASES',
url: ApiTable.postMeatadataDatabases, url: ApiTable.postMetadataDatabases,
msg: { option: '新建元数据' }, msg: { option: '新建元数据' },
reducer: {} reducer: {}
}); });
} }
export function putMeatadataDatabases(id, data) { export function putMetadataDatabases(id, data) {
return dispatch => basicAction({ return dispatch => basicAction({
type: 'put', type: 'put',
data: data, data: data,
dispatch, dispatch,
actionType: 'PUT_METADATA_DATABASES', actionType: 'PUT_METADATA_DATABASES',
url: ApiTable.putMeatadataDatabases.replace('{id}', id), url: ApiTable.putMetadataDatabases.replace('{id}', id),
msg: { msg: {
option: '修改元数据', option: '修改元数据',
} }
}); });
} }
export function delMeatadataDatabases(id) { export function delMetadataDatabases(id) {
return dispatch => basicAction({ return dispatch => basicAction({
type: 'del', type: 'del',
dispatch, dispatch,
actionType: 'DELETE_METADATA_DATABASES', actionType: 'DELETE_METADATA_DATABASES',
url: ApiTable.delMeatadataDatabases.replace('{id}', id), url: ApiTable.delMetadataDatabases.replace('{id}', id),
msg: { msg: {
option: '删除元数据', option: '删除元数据',
} }
@ -147,3 +147,38 @@ export function getMetadataDatabasesById(id) {
reducer: { name: 'metadataDatabasesInfo' } reducer: { name: 'metadataDatabasesInfo' }
}); });
} }
export function getTagMetadata(id, type) {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_TAG_METADATA',
url: ApiTable.getTagMetadata.replace('{id}', id) + `?type=${type}`,
msg: { error: '获取元数据已打标数据失败' },
reducer: { name: 'tagMetadata' }
});
}
export function postMetadataResourceApplications(data) {
return dispatch => basicAction({
type: 'post',
data: data,
dispatch: dispatch,
actionType: 'POST_METADATA_RESOURCE_APPLICATIONS',
url: ApiTable.postMetadataResourceApplications,
msg: { option: '申请资源' },
reducer: {}
});
}
export function getMetadataResourceApplications(params) {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
query: params,
actionType: 'GET_TAG_METADATA',
url: ApiTable.getMetadataResourceApplications,
msg: { error: '获取元数据资源申请记录失败' },
reducer: { name: 'metadataResourceApplications' }
});
}

4
web/client/src/sections/metadataManagement/components/metadataDatabaseModal.js

@ -137,8 +137,8 @@ const MetadataDatabaseModal = (props) => {
<Form.Item <Form.Item
label='详情' label='详情'
name='description' name='description'
rules={[{ max: 255, message: `描述不超过255个字符` }]}> rules={[{ max: 255, message: `详情不超过255个字符` }]}>
<TextArea rows={4} style={{ width: '90%' }} placeholder={`请输入描述`} /> <TextArea rows={4} style={{ width: '90%' }} placeholder={`请输入详情`} />
</Form.Item> </Form.Item>
{renderModelItems()} {renderModelItems()}
</Form> </Form>

53
web/client/src/sections/metadataManagement/components/metadataResourceModal.js

@ -0,0 +1,53 @@
import React, { useEffect, useState } from 'react';
import { Modal, Input, Form } from 'antd';
const { TextArea } = Input;
const MetadataResourceModal = (props) => {
const { onConfirm, onCancel, editData } = props;
const [form] = Form.useForm();
useEffect(() => {
}, []);
const handleOk = () => {
form.validateFields().then(values => {
if (onConfirm) {
onConfirm({ ...editData.record, ...values });
}
})
}
const validatorNull = (rule, value, getFieldValue, validateFields, label) => {
if (!value || !value.trim().length) {
return Promise.reject(new Error(`${label}不可空字符串`));
}
return Promise.resolve();
}
return (
<Modal title={'申请资源'} open={true} destroyOnClose
okText='确定' width={800}
onOk={() => handleOk(null)}
onCancel={onCancel}>
<Form form={form} labelCol={{ span: 6 }} wrapperCol={{ span: 18 }} initialValues={editData.record || {}}>
<Form.Item
label='资源名称'
name='resourceName'
rules={[{ required: true, message: '资源名称不可空' }]}>
<Input disabled style={{ width: '90%' }} />
</Form.Item>
<Form.Item
label='申请人'
name='applyByName'
rules={[{ required: true, message: '申请人不可空' }]}>
<Input disabled style={{ width: '90%' }} />
</Form.Item>
<Form.Item
label='需求描述'
name='requirements'
rules={[{ required: true, message: '' }, { max: 255, message: `需求描述不超过255个字符` },
({ getFieldValue, validateFields }) => ({
validator(_, value) { return validatorNull(_, value, getFieldValue, validateFields, '需求描述') }
})]}>
<TextArea rows={4} style={{ width: '90%' }} placeholder={`请输入需求描述`} />
</Form.Item>
</Form>
</Modal >
)
}
export default MetadataResourceModal;

79
web/client/src/sections/metadataManagement/components/metadataTagModal.js

@ -0,0 +1,79 @@
import React, { useEffect, useState } from 'react';
import { Modal, Form, Select, } from 'antd';
const MetadataDatabaseTagModal = (props) => {
const { onConfirm, onCancel, editData, tagList } = props;
const [form] = Form.useForm();
const [tagSet, setTagSet] = useState(editData.record.tagSet || []);
useEffect(() => {
}, []);
const handleOk = () => {
form.validateFields().then(values => {
if (onConfirm) {
onConfirm({ database: editData.record.id, ...values });
}
})
}
const renderTagItems = () => {
let tags = [];
if (tagSet.length) {
tagList.map(t => {
if (tagSet.includes(t.tagSetId)) {
t.tags.map(t => {
tags.push(<Select.Option value={t.id} key={`tag-${t.id}`}>{t.name}</Select.Option>)
})
}
});
}
return tags;
}
return (
<Modal title={'打标'} open={true} destroyOnClose
okText='确定' width={800}
onOk={() => handleOk(null)}
onCancel={onCancel}>
<Form form={form} labelCol={{ span: 6 }} wrapperCol={{ span: 18 }} initialValues={editData.record}>
<Form.Item
label="标签集"
name='tagSet'
rules={[{ required: true, message: '请选择标签集' }]}>
<Select
maxTagCount={5}
placeholder='请选择标签集'
style={{ width: '90%' }}
showSearch
optionFilterProp='children'
getPopupContainer={triggerNode => triggerNode.parentNode}
filterOption={(input, option) => option.props.children
.toLowerCase().indexOf(input.toLowerCase()) >= 0}
onChange={value => {
setTagSet(value)
form.setFieldValue('tags', []);
}}
mode="multiple"
>
{tagList.map(t => <Select.Option value={t.tagSetId} key={`tagSet-${t.tagSetId}`}>{t.tagSetName}</Select.Option>)}
</Select>
</Form.Item>
<Form.Item
label="标签"
name='tags'
rules={[{ required: true, message: '请选择标签' }]}>
<Select
maxTagCount={5}
placeholder='请选择标签'
style={{ width: '90%' }}
showSearch
optionFilterProp='children'
getPopupContainer={triggerNode => triggerNode.parentNode}
filterOption={(input, option) => option.props.children
.toLowerCase().indexOf(input.toLowerCase()) >= 0}
mode="multiple"
>
{renderTagItems()}
</Select>
</Form.Item>
</Form>
</Modal >
)
}
export default MetadataDatabaseTagModal;

87
web/client/src/sections/metadataManagement/containers/databasesTable.js

@ -6,10 +6,12 @@ import moment from 'moment';
import FileSaver from 'file-saver'; import FileSaver from 'file-saver';
import MetadataDatabaseModal from '../components/metadataDatabaseModal'; import MetadataDatabaseModal from '../components/metadataDatabaseModal';
import { ModelTypes } from '../constants/index'; import { ModelTypes } from '../constants/index';
import MetadataTagModal from '../components/metadataTagModal';
import MetadataResourceModal from '../components/metadataResourceModal';
const DatabaseTable = (props) => { const DatabaseTable = (props) => {
const { user, dispatch, actions, clientHeight, resourceCatalogId, resourceCatalogKey, const { user, dispatch, actions, clientHeight, resourceCatalogId, resourceCatalogKey,
resourceCatalogPath, isRequesting, metadataModels, setView } = props; resourceCatalogPath, isRequesting, metadataModels, setView, tagList, metadataResourceApplications } = props;
const { metadataManagement } = actions; const { metadataManagement } = actions;
const SortValues = { 'ascend': 'asc', 'descend': 'desc' }; const SortValues = { 'ascend': 'asc', 'descend': 'desc' };
const [tableData, setTableData] = useState([]); const [tableData, setTableData] = useState([]);
@ -22,8 +24,13 @@ const DatabaseTable = (props) => {
const [selectedRows, setSelectedRows] = useState([]); const [selectedRows, setSelectedRows] = useState([]);
const [modalVisible, setModalVisible] = useState(false); const [modalVisible, setModalVisible] = useState(false);
const [editData, setEditData] = useState({}); const [editData, setEditData] = useState({});
const [tagModalVisible, setTagModalVisible] = useState(false);
const [editTagData, setEditTagData] = useState({});
const [resourceModalVisible, setResourceModalVisible] = useState(false);
const [editResourceData, setEditResourceData] = useState({});
useEffect(() => { useEffect(() => {
dispatch(metadataManagement.getTagList());
setCreateAtSort('descend'); setCreateAtSort('descend');
initData({ limit, offset: currentPage - 1, orderDirection: SortValues[createAtSort] }); initData({ limit, offset: currentPage - 1, orderDirection: SortValues[createAtSort] });
}, [resourceCatalogId]); }, [resourceCatalogId]);
@ -33,8 +40,17 @@ const DatabaseTable = (props) => {
if (res.success) { if (res.success) {
setTableData(res.payload.data.rows); setTableData(res.payload.data.rows);
setTableDataCount(res.payload.data.count); setTableDataCount(res.payload.data.count);
let resourceNames = [];
res.payload.data.rows.map(r => {
if (r.type === '表') {
resourceNames.push(r.name);
} }
}) })
if (resourceNames.length)
dispatch(metadataManagement.getMetadataResourceApplications({ resourceNames: resourceNames.join(','), type: '库表' }))
}
})
} }
const onView = (record) => { const onView = (record) => {
setView({ path: '/' + resourceCatalogPath.join('/'), ...record }); setView({ path: '/' + resourceCatalogPath.join('/'), ...record });
@ -48,15 +64,44 @@ const DatabaseTable = (props) => {
}) })
} }
const confirmDelete = (id) => { const confirmDelete = (id) => {
dispatch(metadataManagement.delMeatadataDatabases(id)).then(res => { dispatch(metadataManagement.delMetadataDatabases(id)).then(res => {
if (res.success) { if (res.success) {
onSearch(); setModalVisible(false); onSearch(); setModalVisible(false);
} }
}); });
} }
const marking = (id) => { } const marking = (id) => {
const applyResources = (id) => { } dispatch(metadataManagement.getTagMetadata(id, 'database')).then(res => {
if (res.success) {
const obj = { tagSet: [], tags: [], id: id };
if (res.payload.data.length) {
obj.tagSet = res.payload.data.map(d => d.tagSet);
obj.tags = res.payload.data.map(d => d.id);
}
setEditTagData({ record: obj });
setTagModalVisible(true);
}
})
}
const onConfirmTag = (values) => {
dispatch(metadataManagement.postTagMetadata(values)).then(res => {
if (res.success) {
onSearch(); setTagModalVisible(false);
}
});
}
const applyResources = (record) => {
setEditResourceData({ record: { resourceName: record.name, applyBy: user.id, applyByName: user.name, resourceType: '库表' } });
setResourceModalVisible(true);
}
const onConfirmResource = (values) => {
dispatch(metadataManagement.postMetadataResourceApplications(values)).then(res => {
if (res.success) {
onSearch(); setResourceModalVisible(false);
}
});
}
const onTableChange = (pagination, filters, sorter) => { const onTableChange = (pagination, filters, sorter) => {
let limit = Number.parseInt(pagination.pageSize); let limit = Number.parseInt(pagination.pageSize);
let offset = Number.parseInt(pagination.current) - 1; let offset = Number.parseInt(pagination.current) - 1;
@ -123,6 +168,8 @@ const DatabaseTable = (props) => {
dataIndex: 'action', dataIndex: 'action',
width: '8%', width: '8%',
render: (text, record) => { render: (text, record) => {
let resourceApplicationsRecords = metadataResourceApplications.filter(ra =>
ra.applyBy == user.id && ra.resourceName === record.name);
return <ButtonGroup> return <ButtonGroup>
<a onClick={() => onView(record)}>查看</a> <a onClick={() => onView(record)}>查看</a>
<a style={{ marginLeft: 10 }} onClick={() => onEdit(record)}>编辑</a> <a style={{ marginLeft: 10 }} onClick={() => onEdit(record)}>编辑</a>
@ -131,7 +178,9 @@ const DatabaseTable = (props) => {
onConfirm={() => confirmDelete(record.id)} onConfirm={() => confirmDelete(record.id)}
> <a style={{ marginLeft: 10 }}>删除</a></Popconfirm> > <a style={{ marginLeft: 10 }}>删除</a></Popconfirm>
{record.type === '表' ? <a style={{ marginLeft: 10 }} onClick={() => marking(record.id)}>打标</a> : null} {record.type === '表' ? <a style={{ marginLeft: 10 }} onClick={() => marking(record.id)}>打标</a> : null}
{record.type === '表' ? <a style={{ marginLeft: 10 }} onClick={() => applyResources(record.id)}>申请资源</a> : null} {record.type === '表' ? resourceApplicationsRecords.length === 0 ?
<a style={{ marginLeft: 10 }} onClick={() => applyResources(record)}>申请资源</a> :
<span style={{ marginLeft: 10, color: "#c0c0c0" }} title='已存在资源申请'>申请资源</span> : null}
</ButtonGroup> </ButtonGroup>
} }
}]; }];
@ -187,12 +236,12 @@ const DatabaseTable = (props) => {
let obj = {} let obj = {}
if (editData.add) { if (editData.add) {
obj = { createBy: user.id, catalog: resourceCatalogId, catalogKey: resourceCatalogKey, ...values } obj = { createBy: user.id, catalog: resourceCatalogId, catalogKey: resourceCatalogKey, ...values }
dispatch(metadataManagement.postMeatadataDatabases(obj)).then(() => { dispatch(metadataManagement.postMetadataDatabases(obj)).then(() => {
onSearch(); setModalVisible(false); onSearch(); setModalVisible(false);
}); });
} else { } else {
obj = { catalog: resourceCatalogId, catalogKey: resourceCatalogKey, ...values } obj = { catalog: resourceCatalogId, catalogKey: resourceCatalogKey, ...values }
dispatch(metadataManagement.putMeatadataDatabases(editData.record.id, obj)).then(res => { dispatch(metadataManagement.putMetadataDatabases(editData.record.id, obj)).then(res => {
if (res.success) { if (res.success) {
onSearch(); setModalVisible(false); onSearch(); setModalVisible(false);
} }
@ -269,17 +318,35 @@ const DatabaseTable = (props) => {
onCancel={() => setModalVisible(false)} onCancel={() => setModalVisible(false)}
onConfirm={onConfirm} /> : '' onConfirm={onConfirm} /> : ''
} }
{
tagModalVisible ?
<MetadataTagModal
tagList={tagList}
editData={editTagData}
onCancel={() => setTagModalVisible(false)}
onConfirm={onConfirmTag} /> : ''
}
{
resourceModalVisible ?
<MetadataResourceModal
editData={editResourceData}
onCancel={() => setResourceModalVisible(false)}
onConfirm={onConfirmResource} /> : ''
}
</Spin > </Spin >
} }
function mapStateToProps(state) { function mapStateToProps(state) {
const { global, auth, metadataDatabases, metadataModels } = state; const { global, auth, metadataDatabases, metadataModels, tagList, tagMetadata, metadataResourceApplications } = state;
return { return {
user: auth.user, user: auth.user,
actions: global.actions, actions: global.actions,
clientHeight: global.clientHeight, clientHeight: global.clientHeight,
isRequesting: metadataDatabases.isRequesting || metadataModels.isRequesting, isRequesting: metadataDatabases.isRequesting || metadataModels.isRequesting || tagList.isRequesting
|| tagMetadata.isRequesting || metadataResourceApplications.isRequesting,
metadataModels: metadataModels.data, metadataModels: metadataModels.data,
tagList: tagList.data || [],
tagMetadata: tagMetadata.data || [],
metadataResourceApplications: metadataResourceApplications.data || []
}; };
} }
export default connect(mapStateToProps)(DatabaseTable) export default connect(mapStateToProps)(DatabaseTable)

2
web/client/src/sections/metadataManagement/containers/metadataDetails.js

@ -75,7 +75,7 @@ const MetadataDetails = (props) => {
createBy: user.id, catalog: databasesRecord.catalog, createBy: user.id, catalog: databasesRecord.catalog,
catalogKey: sessionStorage.getItem('jumpSelectedKey'), ...values catalogKey: sessionStorage.getItem('jumpSelectedKey'), ...values
} }
dispatch(metadataManagement.postMeatadataDatabases(obj)).then(() => { dispatch(metadataManagement.postMetadataDatabases(obj)).then(() => {
setCurrentPage(1); setCurrentPage(1);
initTableData({ id: databasesRecord.id, limit, offset: 0 }); initTableData({ id: databasesRecord.id, limit, offset: 0 });
setModalVisible(false); setModalVisible(false);

14
web/client/src/utils/webapi.js

@ -27,11 +27,15 @@ export const ApiTable = {
getMetadataFiles: 'metadata/files', getMetadataFiles: 'metadata/files',
getMetadataRestapis: 'metadata/restapis', getMetadataRestapis: 'metadata/restapis',
getMetadataModels: 'metadata/models', getMetadataModels: 'metadata/models',
//库表元数据增删改 //库表元数据增删改、等配置
postMeatadataDatabases: 'meatadata/databases', postMetadataDatabases: 'metadata/databases',
putMeatadataDatabases: 'meatadata/databases/{id}', putMetadataDatabases: 'metadata/databases/{id}',
delMeatadataDatabases: 'meatadata/databases/{id}', delMetadataDatabases: 'metadata/databases/{id}',
getMetadataDatabasesById: 'metadata/databases/{id}', getMetadataDatabasesById: 'metadata/databases/{id}',
postTagMetadata: 'tag/metadata',
getTagMetadata: 'tag/metadata/{id}',
getMetadataResourceApplications: 'resource-consumption/applications',
postMetadataResourceApplications: 'resource-consumption/applications',
//元数据采集-数据源管理 //元数据采集-数据源管理
pgCheckConnect: 'adapter/check/connect', pgCheckConnect: 'adapter/check/connect',
@ -47,7 +51,7 @@ export const ApiTable = {
runTask: 'run/acq/task', runTask: 'run/acq/task',
//采集日志 //采集日志
getLogs:"meta/acq/logs" getLogs: "meta/acq/logs"
}; };
export const RouteTable = { export const RouteTable = {

Loading…
Cancel
Save