From 3bcb297675d6c91ae07767203e2cbd61c46febf7 Mon Sep 17 00:00:00 2001 From: wenlele Date: Thu, 29 Jun 2023 14:15:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E8=AE=BF=E9=97=AE=E8=A1=A8?= =?UTF-8?q?=E5=88=9B=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/controllers/latestMetadata/index.js | 76 +++++++++++----- api/app/lib/index.js | 5 +- api/app/lib/models/restful_api.js | 89 +++++++++++++++++++ api/app/lib/models/restful_api_record.js | 53 +++++++++++ api/app/lib/routes/latestMetadata/index.js | 4 + scripts/0.0.9/01_alter_t_restful_api.sql | 65 ++++++++++++++ .../dataQuality/containers/documentLibrary.js | 1 - .../actions/businessMetadata.js | 12 +++ .../components/releaseModal.js | 89 +++++++++++++------ web/client/src/utils/webapi.js | 2 + 10 files changed, 344 insertions(+), 52 deletions(-) create mode 100644 api/app/lib/models/restful_api.js create mode 100644 api/app/lib/models/restful_api_record.js create mode 100644 scripts/0.0.9/01_alter_t_restful_api.sql diff --git a/api/app/lib/controllers/latestMetadata/index.js b/api/app/lib/controllers/latestMetadata/index.js index 3776058..46d8ed8 100644 --- a/api/app/lib/controllers/latestMetadata/index.js +++ b/api/app/lib/controllers/latestMetadata/index.js @@ -529,29 +529,29 @@ async function postMetadataResourceApplications (ctx) { try { const { resourceName, applyBy, resourceType, resourceId } = ctx.request.body; if (!resourceName || !applyBy || !resourceType || !resourceId) { + ctx.status = 400; + ctx.body = { message: '参数不全,请重新申请资源' } + } else { + const models = ctx.fs.dc.models; + const postOne = await models.ResourceConsumption.findOne({ + where: { applyBy: applyBy, resourceName: resourceName, resourceId, resourceType, approve_remarks: null } + }); + if (postOne) { ctx.status = 400; - ctx.body = { message: '参数不全,请重新申请资源' } - } else { - const models = ctx.fs.dc.models; - const postOne = await models.ResourceConsumption.findOne({ - where: { applyBy: applyBy, resourceName: resourceName, resourceId, resourceType, approve_remarks: null } - }); - 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": "申请资源失败" - } - } + 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": "申请资源失败" + } + } } //获取元数据资源申请记录 @@ -827,6 +827,35 @@ async function listStructuredData (ctx) { } } } + +//发布REST服务 +async function publishingServices (ctx) { + let message = "发布REST服务失败" + try { + const models = ctx.fs.dc.models; + const data = ctx.request.body; + const { method, url } = data + + + const postOne = await models.MetadataRestapi.findOne({ where: { method: method, url: url } }); + if (postOne) { + message = '路由和请求方式重复' + throw '' + } + + await models.MetadataRestapi.create(data) + + ctx.body = { message: '发布REST服务成功' } + ctx.status = 200; + + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + "message": message + } + } +} module.exports = { getResourceCatalog, postResourceCatalog, @@ -850,5 +879,6 @@ module.exports = { postMetadataRestapis, putMetadataRestapis, delMetadataRestapis, - listStructuredData + listStructuredData, + publishingServices } \ No newline at end of file diff --git a/api/app/lib/index.js b/api/app/lib/index.js index eb4331c..8341704 100644 --- a/api/app/lib/index.js +++ b/api/app/lib/index.js @@ -56,7 +56,7 @@ module.exports.models = function (dc) { const { DataSource, AcquisitionTask, Adapter, User, MetadataDatabase, MetadataFile, MetadataRestapi, AcquisitionLog, ResourceCatalog, - BusinessMetadataDatabase, BusinessMetadataFile, BusinessMetadataRestapi,ResourceConsumption,BusinessRule,StandardDoc + BusinessMetadataDatabase, BusinessMetadataFile, BusinessMetadataRestapi,ResourceConsumption,BusinessRule,StandardDoc,RestfulApi,RestfulApiRecord } = dc.models; AcquisitionTask.belongsTo(DataSource, { foreignKey: 'dataSourceId', targetKey: 'id' }); @@ -92,4 +92,7 @@ module.exports.models = function (dc) { BusinessRule.belongsTo(StandardDoc, { foreignKey: 'ruleBasis', targetKey: 'id' }); StandardDoc.hasMany(BusinessRule, { foreignKey: 'ruleBasis', targetKey: 'id' }); + RestfulApi.belongsTo(RestfulApiRecord, { foreignKey: 'restServiceId', targetKey: 'id' }); + RestfulApiRecord.belongsTo(RestfulApi, { foreignKey: 'restServiceId', targetKey: 'id' }); + }; diff --git a/api/app/lib/models/restful_api.js b/api/app/lib/models/restful_api.js new file mode 100644 index 0000000..f2a00de --- /dev/null +++ b/api/app/lib/models/restful_api.js @@ -0,0 +1,89 @@ +/* eslint-disable*/ + +'use strict'; + +module.exports = dc => { + const DataTypes = dc.ORM; + const sequelize = dc.orm; + const RestfulApi = sequelize.define("restfulApi", { + id: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: null, + comment: "唯一标识", + primaryKey: true, + field: "id", + autoIncrement: true, + unique: "t_restful_api_id_uindex" + }, + name: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: null, + comment: "接口名称", + primaryKey: false, + field: "name", + autoIncrement: false + }, + url: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: null, + comment: "接口路由", + primaryKey: false, + field: "url", + autoIncrement: false + }, + method: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: null, + comment: "请求方法", + primaryKey: false, + field: "method", + autoIncrement: false + }, + table: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "数据库表名称", + primaryKey: false, + field: "table", + autoIncrement: false + }, + conditions: { + type: DataTypes.JSONB, + allowNull: true, + defaultValue: null, + comment: "数据库表查询条件", + primaryKey: false, + field: "conditions", + autoIncrement: false + }, + enabled: { + type: DataTypes.BOOLEAN, + allowNull: true, + defaultValue: null, + comment: "是否已启用", + primaryKey: false, + field: "enabled", + autoIncrement: false + }, + fields: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: null, + comment: '数据库表字段', + primaryKey: false, + field: "fields", + autoIncrement: false + } + }, { + tableName: "t_restful_api", + comment: "", + indexes: [] + }); + dc.models.RestfulApi = RestfulApi; + return RestfulApi; +}; \ No newline at end of file diff --git a/api/app/lib/models/restful_api_record.js b/api/app/lib/models/restful_api_record.js new file mode 100644 index 0000000..c1470b8 --- /dev/null +++ b/api/app/lib/models/restful_api_record.js @@ -0,0 +1,53 @@ +/* eslint-disable*/ + +'use strict'; + +module.exports = dc => { + const DataTypes = dc.ORM; + const sequelize = dc.orm; + const RestfulApiRecord = sequelize.define("restfulApiRecord", { + id: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: null, + comment: "唯一标识", + primaryKey: true, + field: "id", + autoIncrement: true, + unique: "t_restful_api_record_id_uindex" + }, + name: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: null, + comment: "接口名称", + primaryKey: false, + field: "name", + autoIncrement: false + }, + visitTime: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: null, + comment: "访问时间", + primaryKey: false, + field: "visit_time", + autoIncrement: false + }, + token: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: null, + comment: "令牌", + primaryKey: false, + field: "token", + autoIncrement: false + }, + }, { + tableName: "t_restful_api_record", + comment: "", + indexes: [] + }); + dc.models.RestfulApiRecord = RestfulApiRecord; + return RestfulApiRecord; +}; \ No newline at end of file diff --git a/api/app/lib/routes/latestMetadata/index.js b/api/app/lib/routes/latestMetadata/index.js index 2f78a22..70a2110 100644 --- a/api/app/lib/routes/latestMetadata/index.js +++ b/api/app/lib/routes/latestMetadata/index.js @@ -71,4 +71,8 @@ module.exports = function (app, router, opts) { app.fs.api.logAttr['GET/listStructuredData'] = { content: '获取对表的库与字段信息', visible: true }; router.get('/listStructuredData', latestMetadata.listStructuredData); + + app.fs.api.logAttr['POST/publishing/services'] = { content: '发布REST服务', visible: true }; + router.post('/publishing/services', latestMetadata.publishingServices); + }; \ No newline at end of file diff --git a/scripts/0.0.9/01_alter_t_restful_api.sql b/scripts/0.0.9/01_alter_t_restful_api.sql new file mode 100644 index 0000000..d95f80c --- /dev/null +++ b/scripts/0.0.9/01_alter_t_restful_api.sql @@ -0,0 +1,65 @@ +create table t_restful_api +( + id serial not null, + "table" varchar(255) not null, + fields varchar(255) not null, + conditions jsonb not null, + name varchar(255) not null, + method varchar(10) not null, + url varchar(255) not null, + enabled boolean default true not null +); + +comment on table t_restful_api is 'REST服务'; + +comment on column t_restful_api.id is 'ID唯一标识'; + +comment on column t_restful_api."table" is '数据库表名称'; + +comment on column t_restful_api.fields is '数据库表字段'; + +comment on column t_restful_api.conditions is '数据库表查询条件'; + +comment on column t_restful_api.name is '接口名称'; + +comment on column t_restful_api.method is '请求方法'; + +comment on column t_restful_api.url is '接口路由'; + +comment on column t_restful_api.enabled is '是否已启用'; + +create unique index t_restful_api_id_uindex + on t_restful_api (id); + +alter table t_restful_api + add constraint t_restful_api_pk + primary key (id); + + + + + +create table t_restful_api_record +( + id serial not null, + rest_service_id int not null, + visit_time timestamp not null, + token varchar(255) not null +); + +comment on table t_restful_api_record is 'REST服务访问记录'; + +comment on column t_restful_api_record.rest_service_id is 'rest服务id'; + +comment on column t_restful_api_record.visit_time is '访问时间'; + +comment on column t_restful_api_record.token is '令牌'; + +create unique index t_restful_api_record_id_uindex + on t_restful_api_record (id); + +alter table t_restful_api_record + add constraint t_restful_api_record_pk + primary key (id); + + diff --git a/web/client/src/sections/dataQuality/containers/documentLibrary.js b/web/client/src/sections/dataQuality/containers/documentLibrary.js index 1516cc8..515010f 100644 --- a/web/client/src/sections/dataQuality/containers/documentLibrary.js +++ b/web/client/src/sections/dataQuality/containers/documentLibrary.js @@ -148,7 +148,6 @@ function Approve ({ loading, clientHeight, actions, dispatch, }) { } }) - console.log(fileUrl); packBulk({ fileUrl: fileUrl }) } else { if (folderId.current.length > 0) { diff --git a/web/client/src/sections/metadataManagement/actions/businessMetadata.js b/web/client/src/sections/metadataManagement/actions/businessMetadata.js index fe391f3..6c679ac 100644 --- a/web/client/src/sections/metadataManagement/actions/businessMetadata.js +++ b/web/client/src/sections/metadataManagement/actions/businessMetadata.js @@ -163,3 +163,15 @@ export function listStructuredData (query = {}) { reducer: {} }); } + +export function publishingServices (data={}) { + return dispatch => basicAction({ + type: 'post', + data: data, + dispatch: dispatch, + actionType: 'POST_PUBLISHING_SERVICES', + url: ApiTable.publishingServices, + msg: { option: '发布REST服务' }, + reducer: {} + }); +} diff --git a/web/client/src/sections/metadataManagement/components/releaseModal.js b/web/client/src/sections/metadataManagement/components/releaseModal.js index 3474368..0cd0318 100644 --- a/web/client/src/sections/metadataManagement/components/releaseModal.js +++ b/web/client/src/sections/metadataManagement/components/releaseModal.js @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react'; import { connect } from 'react-redux'; -import { Modal, Input, Form, Tabs, Avatar, Checkbox, Button, Select } from 'antd'; +import { Modal, Input, Form, Tabs, Avatar, Checkbox, Button, Select, message } from 'antd'; import { PlusCircleOutlined, MinusCircleOutlined } from '@ant-design/icons'; const { TabPane } = Tabs; const { TextArea } = Input; @@ -14,7 +14,10 @@ const ReleaseModal = ({ actions, dispatch, onConfirm, onCancel, editData = {} }) const [database, setDatabase] = useState({}) const [fieldValue, setFiedValue] = useState([]) const [indeterminate, setIndeterminate] = useState(false) - const [fromData, setFromData] = useState([{ value1: '', value2: '', value3: '' }]) + const [fromData, setFromData] = useState([{ field: '', condition: '', value: '' }]) + const [interfaceName, setInterfaceName] = useState('') + const [interfaceUrl, setInterfaceUrl] = useState('') + const [interfaceMode, setInterfaceMode] = useState('GET') const [sql, setSql] = useState() const [form] = Form.useForm(); useEffect(() => { @@ -37,7 +40,6 @@ const ReleaseModal = ({ actions, dispatch, onConfirm, onCancel, editData = {} }) { value: '<', label: '<' }, { value: '>=', label: '>=' }, { value: '<=', label: '<=' }, - { value: 'BETWEEN', label: 'BETWEEN' }, { value: 'LIKE', label: 'LIKE' }, { value: 'IN', label: 'IN' }] @@ -100,37 +102,37 @@ const ReleaseModal = ({ actions, dispatch, onConfirm, onCancel, editData = {} }) {fromData?.map((f, index) => { return
{ - fromData?.splice(index, 1, { value1: f.value1, value2: v, value3: f.value3 }) + fromData?.splice(index, 1, { field: f.field, condition: v, value: f.value }) setFromData([...fromData]) }} options={operator} allowClear /> { - fromData?.splice(index, 1, { value1: f.value1, value2: f.value2, value3: v?.target?.value }) + fromData?.splice(index, 1, { field: f.field, condition: f.condition, value: v?.target?.value }) setFromData([...fromData]) }} allowClear /> {index == 0 ? { - fromData?.splice(index, 0, { value1: '', value2: '', value3: '' }) + fromData?.splice(index, 0, { field: '', condition: '', value: '' }) setFromData([...fromData]) }} /> : { @@ -143,31 +145,43 @@ const ReleaseModal = ({ actions, dispatch, onConfirm, onCancel, editData = {} }) -
预览SQL:
+
预览SQL: