diff --git a/api/.vscode/launch.json b/api/.vscode/launch.json
index 2217519..e901f66 100644
--- a/api/.vscode/launch.json
+++ b/api/.vscode/launch.json
@@ -16,6 +16,7 @@
"-p 4400",
// 研发
"-g postgres://FashionAdmin:123456@10.8.30.39:5432/GovernmentDataResourceCenter",
+ // "-g postgres://FashionAdmin:123456@10.8.30.156:5432/gdrcenter",
"-b http://10.8.30.160:8085"
]
},
diff --git a/web/client/assets/files/common/1687849649468_5.jpg b/web/client/assets/files/common/1687849649468_5.jpg
new file mode 100644
index 0000000..900b37d
Binary files /dev/null and b/web/client/assets/files/common/1687849649468_5.jpg differ
diff --git a/web/client/assets/files/common/1687849663076_2.jpg b/web/client/assets/files/common/1687849663076_2.jpg
new file mode 100644
index 0000000..3f96826
Binary files /dev/null and b/web/client/assets/files/common/1687849663076_2.jpg differ
diff --git a/web/client/assets/files/common/1687849677583_2.jpg b/web/client/assets/files/common/1687849677583_2.jpg
new file mode 100644
index 0000000..3f96826
Binary files /dev/null and b/web/client/assets/files/common/1687849677583_2.jpg differ
diff --git a/web/client/src/app.js b/web/client/src/app.js
index 60017ea..29ed713 100644
--- a/web/client/src/app.js
+++ b/web/client/src/app.js
@@ -12,6 +12,7 @@ import memberManagement from './sections/memberManagement';
import dataQuality from './sections/dataQuality';
import safetySpecification from './sections/safetySpecification';
import backups from './sections/backups';
+import dataService from './sections/dataService';
const App = props => {
const { projectName } = props
@@ -31,6 +32,7 @@ const App = props => {
resourceRetrieval,
dataQuality,
safetySpecification,
+ dataService,
memberManagement,
backups
]}
diff --git a/web/client/src/sections/dataQuality/components/ruleModal.js b/web/client/src/sections/dataQuality/components/ruleModal.js
index 1e01922..e32c758 100644
--- a/web/client/src/sections/dataQuality/components/ruleModal.js
+++ b/web/client/src/sections/dataQuality/components/ruleModal.js
@@ -5,7 +5,7 @@ import { v4 as uuidv4 } from 'uuid'
import { Tabs, Form, Input, DatePicker, Button, Modal, Radio, Select, TreeSelect } from 'antd';
const { TextArea } = Input;
-const { Option, OptGroup } = Select;
+const { TreeNode } = TreeSelect;
function RuleModal ({ loading, parent, user, actions, dispatch, close, success, treeList, editData }) {
const { dataQuality } = actions
@@ -13,15 +13,23 @@ function RuleModal ({ loading, parent, user, actions, dispatch, close, success,
const [query, setQuery] = useState({ page: 0, limit: 10 });
const [proTableList, setProTableList] = useState({ rows: [], count: 0 });
const [approve, setApprove] = useState()
-
+ const [ruleBasis, setRuleBasis] = useState()
const [form] = Form.useForm();
useEffect(() => {
-
+
}, [])
-
+ let recursive = (data) => {
+ let title = []
+ data?.map(v => {
+ title.push(
+ {recursive(v.children)}
+ )
+ })
+ return title
+ }
return <>
@@ -30,7 +38,7 @@ function RuleModal ({ loading, parent, user, actions, dispatch, close, success,
form.validateFields().then(v => {
// console.log(v);
dispatch(dataQuality.postBusinessRules({
- ...v, id: editData?.id
+ ...v, id: editData?.id, ruleBasis: ruleBasis
})).then(res => {
if (res.success) {
close()
@@ -52,7 +60,7 @@ function RuleModal ({ loading, parent, user, actions, dispatch, close, success,
autoComplete="off"
labelCol={{ span: 4 }} wrapperCol={{ span: 20 }}
>
-
+
@@ -75,16 +83,26 @@ function RuleModal ({ loading, parent, user, actions, dispatch, close, success,
width: 300,
}}
// value={}
- dropdownStyle={{
- maxHeight: 300,
- overflow: 'auto',
- }}
+ // dropdownStyle={{
+ // maxHeight: 300,
+ // overflow: 'auto',
+ // }}
placeholder=""
allowClear
treeDefaultExpandAll
- // onChange={onChange}
- treeData={treeList || []}
- />
+ onChange={(label, extra) => {
+ // console.log(label, extra);
+ }}
+ onSearch={v => {
+ // console.log(v);
+ }}
+ onSelect={(value, node, extra) => {
+ setRuleBasis(node.key)
+ }}
+ // treeData={treeList || []}
+ >
+ {treeList?.length && recursive(treeList)}
+
diff --git a/web/client/src/sections/dataQuality/containers/documentLibrary.js b/web/client/src/sections/dataQuality/containers/documentLibrary.js
index b207704..1516cc8 100644
--- a/web/client/src/sections/dataQuality/containers/documentLibrary.js
+++ b/web/client/src/sections/dataQuality/containers/documentLibrary.js
@@ -74,7 +74,7 @@ function Approve ({ loading, clientHeight, actions, dispatch, }) {
if (name.filter(f => d.name == f.name)?.length) {
name.filter(f => d.name == f.name)?.forEach(s => {
s.number = s.number + 1
- d.name = d.name.slice(0, d.name.lastIndexOf(".")) + '(' + s.number + ')' + d.name.slice(d.name.lastIndexOf("."), d.name.length)
+ d.name = d.name?.slice(0, d.name.lastIndexOf(".")) + '(' + s.number + ')' + d.name?.slice(d.name.lastIndexOf("."), d.name.length)
})
} else {
name.push({ name: d.name, number: 0 })
@@ -83,16 +83,23 @@ function Approve ({ loading, clientHeight, actions, dispatch, }) {
const zip = new JSZip()
let result = []
+ let date = moment().add(8, 'hours').utc();
+ let year = date.year();
+ let month = date.month();
+ let day = date.date();
+ let hours = date.hours();
+ let minutes = date.minutes();
+ let seconds = date.seconds();
fileUrl.map(d => {
let url = d?.url?.replace(/\\/g, '/')
let promise = getFileBlob(url).then((res) => {
- zip.file(d.name, res, { binary: true })
+ zip.file(d.name, res, { binary: true, date: new Date(Date.UTC(year, month, day, hours, minutes, seconds)) })
})
result.push(promise)
})
Promise.all(result).then(() => {
zip.generateAsync({ type: "blob" }).then((res) => {
- saveAs(res, `标准文档.zip`)
+ saveAs(res, `标准文档.zip`);
})
})
}
diff --git a/web/client/src/sections/dataService/actions/documentLibrary.js b/web/client/src/sections/dataService/actions/documentLibrary.js
new file mode 100644
index 0000000..b8af1d1
--- /dev/null
+++ b/web/client/src/sections/dataService/actions/documentLibrary.js
@@ -0,0 +1,78 @@
+'use strict';
+
+import { basicAction } from '@peace/utils'
+import { ApiTable } from '$utils'
+
+export function getStandardDocFolders (query = {}) {
+ return dispatch => basicAction({
+ type: 'get',
+ query,
+ dispatch: dispatch,
+ actionType: 'GET_STANDARD_DOC_FOLDERS',
+ url: `${ApiTable.standardDocFolders}`,
+ msg: { error: '获取标准文档目录列表失败' },
+ reducer: { name: '' }
+ });
+}
+
+
+export function postStandardDocFolders (data = {}) {
+ return dispatch => basicAction({
+ type: 'post',
+ data,
+ dispatch: dispatch,
+ actionType: 'POST_STANDARD_DOC_FOLDERS',
+ url: `${ApiTable.standardDocFolders}`,
+ msg: { option: '标准文档目录新增' },
+ reducer: { name: '' }
+ });
+}
+
+export function postStandardDocs (data = {}) {
+ return dispatch => basicAction({
+ type: 'post',
+ data,
+ dispatch: dispatch,
+ actionType: 'POST_STANDARD_DOCS',
+ url: `${ApiTable.standardDocs}`,
+ msg: { option: '新增标准文档' },
+ reducer: { name: '' }
+ });
+}
+
+export function getStandardDocs (query = {}) {
+ return dispatch => basicAction({
+ type: 'get',
+ query,
+ dispatch: dispatch,
+ actionType: 'GET_STANDARD_DOCS',
+ url: `${ApiTable.standardDocs}`,
+ msg: { error: '获取标准文档列表失败' },
+ reducer: { name: '' }
+ });
+}
+
+export function postFolderFile (data) {
+ return dispatch => basicAction({
+ type: 'post',
+ data,
+ dispatch: dispatch,
+ actionType: 'POST_FOLDER_FILE',
+ url: ApiTable.postFolderFile,
+ msg: { option: '删除文件夹或文件' },
+ reducer: { name: '' }
+ });
+}
+
+export function fetchFiles (data = {}) {
+ return dispatch => basicAction({
+ type: 'post',
+ data,
+ dispatch: dispatch,
+ actionType: 'POST_FETCH_FILES',
+ url: `${ApiTable.fetchFiles}`,
+ msg: { error: '获取文件夹下文件失败' },
+ reducer: { name: '' }
+ });
+}
+
diff --git a/web/client/src/sections/dataService/actions/example.js b/web/client/src/sections/dataService/actions/example.js
new file mode 100644
index 0000000..6b3c25d
--- /dev/null
+++ b/web/client/src/sections/dataService/actions/example.js
@@ -0,0 +1,15 @@
+'use strict';
+
+import { basicAction } from '@peace/utils'
+import { ApiTable } from '$utils'
+
+// export function getMembers(orgId) {
+// return dispatch => basicAction({
+// type: 'get',
+// dispatch: dispatch,
+// actionType: 'GET_MEMBERS',
+// url: `${ApiTable.getEnterprisesMembers.replace('{enterpriseId}', orgId)}`,
+// msg: { error: '获取用户列表失败' },
+// reducer: { name: 'members' }
+// });
+// }
diff --git a/web/client/src/sections/dataService/actions/index.js b/web/client/src/sections/dataService/actions/index.js
new file mode 100644
index 0000000..bb9a933
--- /dev/null
+++ b/web/client/src/sections/dataService/actions/index.js
@@ -0,0 +1,11 @@
+'use strict';
+
+import * as example from './example'
+import * as documentLibrary from './documentLibrary'
+import * as ruleLibrary from './ruleLibrary'
+
+export default {
+ ...example,
+ ...documentLibrary,
+ ...ruleLibrary,
+}
\ No newline at end of file
diff --git a/web/client/src/sections/dataService/actions/ruleLibrary.js b/web/client/src/sections/dataService/actions/ruleLibrary.js
new file mode 100644
index 0000000..b3182d5
--- /dev/null
+++ b/web/client/src/sections/dataService/actions/ruleLibrary.js
@@ -0,0 +1,52 @@
+'use strict';
+
+import { basicAction } from '@peace/utils'
+import { ApiTable } from '$utils'
+
+export function postBusinessRules (data = {}) {
+ let reminder = data?.id ? '修改业务规则' : '新增业务规则'
+ return dispatch => basicAction({
+ type: 'post',
+ data,
+ dispatch: dispatch,
+ actionType: 'POST_BUSINESS_RULES',
+ url: `${ApiTable.businessRules}`,
+ msg: { option: reminder },
+ reducer: { name: '' }
+ });
+}
+
+export function getBusinessRules (query = {}) {
+ return dispatch => basicAction({
+ type: 'get',
+ query,
+ dispatch: dispatch,
+ actionType: 'GET_BUSINESS_RULES',
+ url: `${ApiTable.businessRules}`,
+ msg: { error: '查询业务规则列表失败' },
+ reducer: { name: '' }
+ });
+}
+
+export function delBusinessRules (id) {
+ return dispatch => basicAction({
+ type: 'del',
+ dispatch: dispatch,
+ actionType: 'del_BUSINESS_RULES',
+ url: `${ApiTable.delBusinessRules.replace('{id}', id)}`,
+ msg: { option: '删除业务规则' },
+ reducer: { name: '' }
+ });
+}
+
+export function getRegularBasis (query = {}) {
+ return dispatch => basicAction({
+ type: 'get',
+ query,
+ dispatch: dispatch,
+ actionType: 'GET_REGULAR_BASIS',
+ url: `${ApiTable.regularBasis}`,
+ msg: { error: '查询规则依据列表失败' },
+ reducer: { name: '' }
+ });
+}
diff --git a/web/client/src/sections/dataService/components/fileModal.js b/web/client/src/sections/dataService/components/fileModal.js
new file mode 100644
index 0000000..54356a6
--- /dev/null
+++ b/web/client/src/sections/dataService/components/fileModal.js
@@ -0,0 +1,118 @@
+import React, { useEffect, useState } from 'react'
+import { connect } from 'react-redux';
+import moment from 'moment';
+import { UploadLocal } from '$components';
+
+
+import { Tabs, Form, Input, DatePicker, Button, Modal, Select, Tag } from 'antd';
+
+
+function FileModal ({ loading, parent, user, actions, editData = {}, dispatch, close, success,remove }) {
+
+ const { dataQuality } = actions
+ const [tabsKey, setTabsKey] = useState("stay")
+ const [query, setQuery] = useState({ page: 0, limit: 10 });
+ const [proTableList, setProTableList] = useState({ rows: [], count: 0 });
+ const [approve, setApprove] = useState()
+
+ const [form] = Form.useForm();
+ const [editUrl, setEditUrl] = useState([]);
+ useEffect(() => {
+
+ }, [])
+
+
+
+ const vsjunct = (params) => {
+ if (params.length) {
+ let appendix = []
+ for (let p of params) {
+ appendix.push({
+ fName: p.name,
+ size: p.size,
+ fileSize: p.size,
+ storageUrl: p.storageUrl,//必须有storageUrl
+ })
+ }
+ setEditUrl(appendix)
+ } else {
+ setEditUrl([])
+ }
+ }
+
+ return <>
+ {
+ form.validateFields().then(v => {
+ dispatch(dataQuality.postStandardDocs({
+ ...v,
+ path: v?.files[0]?.url, docName: v?.files[0]?.name,
+ folder: parent || null,
+ })).then(res => {
+ if (res.success) {
+ close()
+ success()
+ }
+ })
+ })
+ }}
+ onCancel={() => {
+ if (form.getFieldValue('files') && form.getFieldValue('files').length) {
+ remove(form.getFieldValue('files')[0]?.url)
+ }
+ close()
+ }}
+ >
+
+
+
+
+
+
+
+
+
+
+ 文件大小不超过40MB,开放资源包含多个文件,建议将文件进行压缩,形成压缩包再上传
+ 支持的文件格式:jpg,png,gif,txt,doc,docx,pdf,xsl,xlsx,zip,rar
+
+
+
+
+ >
+}
+function mapStateToProps (state) {
+ const { global, auth, resourceCatalog } = state;
+ return {
+ user: auth.user,
+ actions: global.actions,
+ clientHeight: global.clientHeight,
+ // resourceCatalog: resourceCatalog?.data || [],
+ // isRequesting: resourceCatalog.isRequesting
+ };
+}
+export default connect(mapStateToProps)(FileModal)
\ No newline at end of file
diff --git a/web/client/src/sections/dataService/components/groupModal.js b/web/client/src/sections/dataService/components/groupModal.js
new file mode 100644
index 0000000..4024fa6
--- /dev/null
+++ b/web/client/src/sections/dataService/components/groupModal.js
@@ -0,0 +1,66 @@
+import React, { useEffect, useState } from 'react'
+import { connect } from 'react-redux';
+import moment from 'moment';
+import { v4 as uuidv4 } from 'uuid'
+
+import { Tabs, Form, Input, DatePicker, Button, Modal, Radio } from 'antd';
+
+
+function GroupModal ({ loading, parent, user, actions, dispatch, close, success, }) {
+
+ const { dataQuality } = actions
+
+ const [form] = Form.useForm();
+ useEffect(() => {
+
+ }, [])
+
+
+
+
+ return <>
+ {
+ form.validateFields().then(v => {
+ dispatch(dataQuality.postStandardDocFolders({
+ ...v,
+ parent: parent || null,
+ })).then(res => {
+ if (res.success) {
+ close()
+ success()
+ }
+ })
+ })
+ }}
+ onCancel={() => {
+ close()
+ }}
+ >
+
+
+
+
+
+
+ >
+}
+function mapStateToProps (state) {
+ const { global, auth, resourceCatalog } = state;
+ return {
+ user: auth.user,
+ actions: global.actions,
+ clientHeight: global.clientHeight,
+ // resourceCatalog: resourceCatalog?.data || [],
+ // isRequesting: resourceCatalog.isRequesting
+ };
+}
+export default connect(mapStateToProps)(GroupModal)
\ No newline at end of file
diff --git a/web/client/src/sections/dataService/components/ruleModal.js b/web/client/src/sections/dataService/components/ruleModal.js
new file mode 100644
index 0000000..1e01922
--- /dev/null
+++ b/web/client/src/sections/dataService/components/ruleModal.js
@@ -0,0 +1,104 @@
+import React, { useEffect, useState } from 'react'
+import { connect } from 'react-redux';
+import moment from 'moment';
+import { v4 as uuidv4 } from 'uuid'
+
+import { Tabs, Form, Input, DatePicker, Button, Modal, Radio, Select, TreeSelect } from 'antd';
+const { TextArea } = Input;
+const { Option, OptGroup } = Select;
+function RuleModal ({ loading, parent, user, actions, dispatch, close, success, treeList, editData }) {
+
+ const { dataQuality } = actions
+ const [tabsKey, setTabsKey] = useState("stay")
+ const [query, setQuery] = useState({ page: 0, limit: 10 });
+ const [proTableList, setProTableList] = useState({ rows: [], count: 0 });
+ const [approve, setApprove] = useState()
+
+ const [form] = Form.useForm();
+ useEffect(() => {
+
+ }, [])
+
+
+
+
+
+
+ return <>
+ {
+ form.validateFields().then(v => {
+ // console.log(v);
+ dispatch(dataQuality.postBusinessRules({
+ ...v, id: editData?.id
+ })).then(res => {
+ if (res.success) {
+ close()
+ success()
+ }
+ })
+ })
+ }}
+ onCancel={() => {
+ close()
+ }}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+}
+function mapStateToProps (state) {
+ const { global, auth, resourceCatalog } = state;
+ return {
+ user: auth.user,
+ actions: global.actions,
+ clientHeight: global.clientHeight,
+ // resourceCatalog: resourceCatalog?.data || [],
+ // isRequesting: resourceCatalog.isRequesting
+ };
+}
+export default connect(mapStateToProps)(RuleModal)
\ No newline at end of file
diff --git a/web/client/src/sections/dataService/containers/index.js b/web/client/src/sections/dataService/containers/index.js
new file mode 100644
index 0000000..53c62aa
--- /dev/null
+++ b/web/client/src/sections/dataService/containers/index.js
@@ -0,0 +1,6 @@
+'use strict';
+
+import ServiceView from './serviceView';
+import ServiceManagement from './serviceManagement';
+
+export {ServiceManagement,ServiceView};
diff --git a/web/client/src/sections/dataService/containers/serviceManagement.js b/web/client/src/sections/dataService/containers/serviceManagement.js
new file mode 100644
index 0000000..7e3156d
--- /dev/null
+++ b/web/client/src/sections/dataService/containers/serviceManagement.js
@@ -0,0 +1,160 @@
+import React, { useEffect, useState } from 'react'
+import { connect } from 'react-redux';
+import moment from 'moment';
+import { RouteRequest } from '@peace/utils';
+import { RouteTable } from '$utils'
+
+import { Tabs, Form, Input, Space, Button, Table, Popconfirm } from 'antd';
+const { Search } = Input;
+import { CreditCardFilled, FilePdfOutlined } from '@ant-design/icons';
+import { agent } from 'superagent';
+
+import RuleModal from '../components/ruleModal';
+
+
+function ServiceManagement ({ loading, clientHeight, actions, dispatch, }) {
+
+ const { dataService } = actions
+ const [query, setQuery] = useState({ page: 0, limit: 10 });
+ const [ruleModal, setRuleModal] = useState(false)
+ const [editData, setEditData] = useState({})
+ const [keyword, setKeyword] = useState()
+ const [tableList, setTableList] = useState({ rows: [], count: 0 });
+ const [treeList, setTreeLista] = useState([])
+ useEffect(() => {
+ resourceData()
+ // dispatch(dataQuality.getRegularBasis()).then(res => {
+ // if (res.success) {
+ // setTreeLista(res.payload.data)
+ // }
+ // })
+ }, [])
+
+
+ let resourceData = (data) => {
+ // let params = data || query
+ // dispatch(dataService.getBusinessRules({ keyword: keyword, ...params, })).then(res => {
+ // if (res.success) {
+ // setTableList({ rows: res.payload.data?.rows, count: res.payload.data?.count })
+
+ // }
+ // })
+ }
+
+ const columns = [{
+ title: '接口名称',
+ dataIndex: 'name',
+ }, {
+ title: '接口路由',
+ dataIndex: 'description',
+ }, {
+ title: '接口类型',
+ dataIndex: 'problemType',
+ }, {
+ title: '状态',
+ dataIndex: 'problemLevel'
+ }, {
+ title: '操作',
+ dataIndex: 'handle',
+ // ellipsis: true,
+ render: (text, record) =>
+
+
+
{
+ dispatch(dataQuality.delBusinessRules(record.id)).then(res => {
+ if (res.success) {
+ setQuery({ limit: 10, page: 0 });
+ resourceData({ limit: 10, page: 0, keyword })
+ }
+ })
+ }}
+ >
+
+
+
+
+ },
+ ];
+
+
+ return <>
+
+
+
+ {
+ setKeyword(e?.target?.value)
+ }}
+ style={{
+ width: 266, marginRight: 10
+ }}
+ />
+
+
+
+
+
+ { return {`共${Math.ceil(total / query?.limit)}页,${total}项`} },
+ onChange: (page, pageSize) => {
+ setQuery({ limit: pageSize, page: page - 1 });
+ resourceData({ limit: pageSize, page: page - 1, keyword });
+ }
+ }}
+ />
+
+ {
+ ruleModal ?
+ {
+ setRuleModal(false);
+ setEditData({})
+ }}
+ success={() => {
+ resourceData({ limit: 10, page: 0, keyword })
+ }
+ }
+ /> : ""
+ }
+
+
+ >
+}
+function mapStateToProps (state) {
+ const { global, auth, resourceCatalog } = state;
+ return {
+ user: auth.user,
+ actions: global.actions,
+ clientHeight: global.clientHeight,
+ // resourceCatalog: resourceCatalog?.data || [],
+ // isRequesting: resourceCatalog.isRequesting
+ };
+}
+export default connect(mapStateToProps)(ServiceManagement)
\ No newline at end of file
diff --git a/web/client/src/sections/dataService/containers/serviceView.js b/web/client/src/sections/dataService/containers/serviceView.js
new file mode 100644
index 0000000..eece3eb
--- /dev/null
+++ b/web/client/src/sections/dataService/containers/serviceView.js
@@ -0,0 +1,158 @@
+import React, { useEffect, useState } from 'react'
+import { connect } from 'react-redux';
+import moment from 'moment';
+import { RouteRequest } from '@peace/utils';
+import { RouteTable } from '$utils'
+
+import { Tabs, Form, Input, Space, Button, Table, Popconfirm } from 'antd';
+const { Search } = Input;
+import { CreditCardFilled, FilePdfOutlined } from '@ant-design/icons';
+import { agent } from 'superagent';
+
+import RuleModal from '../components/ruleModal';
+
+
+function ServiceView ({ loading, clientHeight, actions, dispatch, }) {
+
+ const { dataService } = actions
+ const [query, setQuery] = useState({ page: 0, limit: 10 });
+ const [ruleModal, setRuleModal] = useState(false)
+ const [editData, setEditData] = useState({})
+ const [keyword, setKeyword] = useState()
+ const [tableList, setTableList] = useState({ rows: [], count: 0 });
+ const [treeList, setTreeLista] = useState([])
+ useEffect(() => {
+ resourceData()
+ // dispatch(dataQuality.getRegularBasis()).then(res => {
+ // if (res.success) {
+ // setTreeLista(res.payload.data)
+ // }
+ // })
+ }, [])
+
+
+ let resourceData = (data) => {
+ // let params = data || query
+ // dispatch(dataService.getBusinessRules({ keyword: keyword, ...params, })).then(res => {
+ // if (res.success) {
+ // setTableList({ rows: res.payload.data?.rows, count: res.payload.data?.count })
+
+ // }
+ // })
+ }
+
+ const columns = [{
+ title: '接口名称',
+ dataIndex: 'name',
+ }, {
+ title: '接口路由',
+ dataIndex: 'description',
+ }, {
+ title: '接口类型',
+ dataIndex: 'problemType',
+ }, {
+ title: '状态',
+ dataIndex: 'problemLevel'
+ }, {
+ title: '操作',
+ dataIndex: 'handle',
+ // ellipsis: true,
+ render: (text, record) =>
+
+
+
{
+ dispatch(dataQuality.delBusinessRules(record.id)).then(res => {
+ if (res.success) {
+ setQuery({ limit: 10, page: 0 });
+ resourceData({ limit: 10, page: 0, keyword })
+ }
+ })
+ }}
+ >
+
+
+
+
+ },
+ ];
+
+ return <>
+
+
+ {
+ setKeyword(e?.target?.value)
+ }}
+ style={{
+ width: 266, marginRight: 10
+ }}
+ />
+
+
+
+
+
+ { return {`共${Math.ceil(total / query?.limit)}页,${total}项`} },
+ onChange: (page, pageSize) => {
+ setQuery({ limit: pageSize, page: page - 1 });
+ resourceData({ limit: pageSize, page: page - 1, keyword });
+ }
+ }}
+ />
+
+ {
+ ruleModal ?
+ {
+ setRuleModal(false);
+ setEditData({})
+ }}
+ success={() => {
+ resourceData({ limit: 10, page: 0, keyword })
+ }
+ }
+ /> : ""
+ }
+
+
+ >
+}
+function mapStateToProps (state) {
+ const { global, auth, resourceCatalog } = state;
+ return {
+ user: auth.user,
+ actions: global.actions,
+ clientHeight: global.clientHeight,
+ // resourceCatalog: resourceCatalog?.data || [],
+ // isRequesting: resourceCatalog.isRequesting
+ };
+}
+export default connect(mapStateToProps)(ServiceView)
\ No newline at end of file
diff --git a/web/client/src/sections/dataService/index.js b/web/client/src/sections/dataService/index.js
new file mode 100644
index 0000000..e5c603b
--- /dev/null
+++ b/web/client/src/sections/dataService/index.js
@@ -0,0 +1,15 @@
+'use strict';
+
+import reducers from './reducers';
+import routes from './routes';
+import actions from './actions';
+import { getNavItem } from './nav-item';
+
+export default {
+ key: 'dataService',
+ name: '数据服务',
+ reducers: reducers,
+ routes: routes,
+ actions: actions,
+ getNavItem: getNavItem
+};
\ No newline at end of file
diff --git a/web/client/src/sections/dataService/nav-item.js b/web/client/src/sections/dataService/nav-item.js
new file mode 100644
index 0000000..8b4512d
--- /dev/null
+++ b/web/client/src/sections/dataService/nav-item.js
@@ -0,0 +1,19 @@
+import React from 'react';
+import { Link } from 'react-router-dom';
+import { Menu } from 'antd';
+import { CarryOutOutlined } from '@ant-design/icons';
+const SubMenu = Menu.SubMenu;
+
+export function getNavItem (user) {
+ return (
+ } title='数据服务'>
+
+
+ 服务管理
+
+
+ 服务查看
+
+ SubMenu >
+ );
+}
\ No newline at end of file
diff --git a/web/client/src/sections/dataService/reducers/index.js b/web/client/src/sections/dataService/reducers/index.js
new file mode 100644
index 0000000..7ed1088
--- /dev/null
+++ b/web/client/src/sections/dataService/reducers/index.js
@@ -0,0 +1,5 @@
+'use strict';
+
+export default {
+
+}
\ No newline at end of file
diff --git a/web/client/src/sections/dataService/routes.js b/web/client/src/sections/dataService/routes.js
new file mode 100644
index 0000000..d9ca6c0
--- /dev/null
+++ b/web/client/src/sections/dataService/routes.js
@@ -0,0 +1,22 @@
+'use strict';
+import { ServiceManagement,ServiceView } from './containers';
+export default [{
+ type: 'inner',
+ route: {
+ path: '/dataService',
+ key: 'dataService',
+ breadcrumb: '数据质量',
+ // 不设置 component 则面包屑禁止跳转
+ childRoutes: [{
+ path: '/serviceManagement',
+ key: 'serviceManagement',
+ component: ServiceManagement,
+ breadcrumb: '服务管理'
+ }, {
+ path: '/serviceView',
+ key: 'serviceView',
+ component: ServiceView,
+ breadcrumb: '服务查看'
+ }]
+ }
+}];
\ No newline at end of file
diff --git a/web/client/src/sections/safetySpecification/containers/specificationLibrary.js b/web/client/src/sections/safetySpecification/containers/specificationLibrary.js
index 0e5fe6e..c34657e 100644
--- a/web/client/src/sections/safetySpecification/containers/specificationLibrary.js
+++ b/web/client/src/sections/safetySpecification/containers/specificationLibrary.js
@@ -60,10 +60,17 @@ function SpecificationLibrary ({ loading, clientHeight, actions, dispatch, }) {
function packBulk ({ fileUrl, folderId }) {
const zip = new JSZip()
let result = []
+ let date = moment().add(8, 'hours').utc();
+ let year = date.year();
+ let month = date.month();
+ let day = date.date();
+ let hours = date.hours();
+ let minutes = date.minutes();
+ let seconds = date.seconds();
fileUrl.map(d => {
let url = d?.url?.replace(/\\/g, '/')
let promise = getFileBlob(url).then((res) => {
- zip.file(d.name, res, { binary: true })
+ zip.file(d.name, res, { binary: true, date: new Date(Date.UTC(year, month, day, hours, minutes, seconds)) })
})
result.push(promise)
})