Browse Source

数据服务前端页面

master
wenlele 1 year ago
parent
commit
e7c52b214d
  1. 1
      api/.vscode/launch.json
  2. BIN
      web/client/assets/files/common/1687849649468_5.jpg
  3. BIN
      web/client/assets/files/common/1687849663076_2.jpg
  4. BIN
      web/client/assets/files/common/1687849677583_2.jpg
  5. 2
      web/client/src/app.js
  6. 44
      web/client/src/sections/dataQuality/components/ruleModal.js
  7. 13
      web/client/src/sections/dataQuality/containers/documentLibrary.js
  8. 78
      web/client/src/sections/dataService/actions/documentLibrary.js
  9. 15
      web/client/src/sections/dataService/actions/example.js
  10. 11
      web/client/src/sections/dataService/actions/index.js
  11. 52
      web/client/src/sections/dataService/actions/ruleLibrary.js
  12. 118
      web/client/src/sections/dataService/components/fileModal.js
  13. 66
      web/client/src/sections/dataService/components/groupModal.js
  14. 104
      web/client/src/sections/dataService/components/ruleModal.js
  15. 6
      web/client/src/sections/dataService/containers/index.js
  16. 160
      web/client/src/sections/dataService/containers/serviceManagement.js
  17. 158
      web/client/src/sections/dataService/containers/serviceView.js
  18. 15
      web/client/src/sections/dataService/index.js
  19. 19
      web/client/src/sections/dataService/nav-item.js
  20. 5
      web/client/src/sections/dataService/reducers/index.js
  21. 22
      web/client/src/sections/dataService/routes.js
  22. 9
      web/client/src/sections/safetySpecification/containers/specificationLibrary.js

1
api/.vscode/launch.json

@ -16,6 +16,7 @@
"-p 4400", "-p 4400",
// //
"-g postgres://FashionAdmin:123456@10.8.30.39:5432/GovernmentDataResourceCenter", "-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" "-b http://10.8.30.160:8085"
] ]
}, },

BIN
web/client/assets/files/common/1687849649468_5.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

BIN
web/client/assets/files/common/1687849663076_2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
web/client/assets/files/common/1687849677583_2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

2
web/client/src/app.js

@ -12,6 +12,7 @@ import memberManagement from './sections/memberManagement';
import dataQuality from './sections/dataQuality'; import dataQuality from './sections/dataQuality';
import safetySpecification from './sections/safetySpecification'; import safetySpecification from './sections/safetySpecification';
import backups from './sections/backups'; import backups from './sections/backups';
import dataService from './sections/dataService';
const App = props => { const App = props => {
const { projectName } = props const { projectName } = props
@ -31,6 +32,7 @@ const App = props => {
resourceRetrieval, resourceRetrieval,
dataQuality, dataQuality,
safetySpecification, safetySpecification,
dataService,
memberManagement, memberManagement,
backups backups
]} ]}

44
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'; import { Tabs, Form, Input, DatePicker, Button, Modal, Radio, Select, TreeSelect } from 'antd';
const { TextArea } = Input; const { TextArea } = Input;
const { Option, OptGroup } = Select; const { TreeNode } = TreeSelect;
function RuleModal ({ loading, parent, user, actions, dispatch, close, success, treeList, editData }) { function RuleModal ({ loading, parent, user, actions, dispatch, close, success, treeList, editData }) {
const { dataQuality } = actions 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 [query, setQuery] = useState({ page: 0, limit: 10 });
const [proTableList, setProTableList] = useState({ rows: [], count: 0 }); const [proTableList, setProTableList] = useState({ rows: [], count: 0 });
const [approve, setApprove] = useState() const [approve, setApprove] = useState()
const [ruleBasis, setRuleBasis] = useState()
const [form] = Form.useForm(); const [form] = Form.useForm();
useEffect(() => { useEffect(() => {
}, []) }, [])
let recursive = (data) => {
let title = []
data?.map(v => {
title.push(<TreeNode value={v.title} title={v.title} key={v.value} disabled={v.disabled} >
{recursive(v.children)}
</TreeNode>)
})
return title
}
return <> return <>
@ -30,7 +38,7 @@ function RuleModal ({ loading, parent, user, actions, dispatch, close, success,
form.validateFields().then(v => { form.validateFields().then(v => {
// console.log(v); // console.log(v);
dispatch(dataQuality.postBusinessRules({ dispatch(dataQuality.postBusinessRules({
...v, id: editData?.id ...v, id: editData?.id, ruleBasis: ruleBasis
})).then(res => { })).then(res => {
if (res.success) { if (res.success) {
close() close()
@ -52,7 +60,7 @@ function RuleModal ({ loading, parent, user, actions, dispatch, close, success,
autoComplete="off" autoComplete="off"
labelCol={{ span: 4 }} wrapperCol={{ span: 20 }} labelCol={{ span: 4 }} wrapperCol={{ span: 20 }}
> >
<Form.Item label="名称" name="name" initialValue={editData?.name} rules={[{ required: true, message: '请输入分组名称,最多50字', max: 50}]}> <Form.Item label="名称" name="name" initialValue={editData?.name} rules={[{ required: true, message: '请输入分组名称,最多50字', max: 50 }]}>
<Input allowClear placeholder='请输入分组名称' style={{ width: 300 }} /> <Input allowClear placeholder='请输入分组名称' style={{ width: 300 }} />
</Form.Item> </Form.Item>
<Form.Item label="描述" name="description" initialValue={editData?.description} rules={[{ required: true, message: '请输入分组名称' }]}> <Form.Item label="描述" name="description" initialValue={editData?.description} rules={[{ required: true, message: '请输入分组名称' }]}>
@ -75,16 +83,26 @@ function RuleModal ({ loading, parent, user, actions, dispatch, close, success,
width: 300, width: 300,
}} }}
// value={} // value={}
dropdownStyle={{ // dropdownStyle={{
maxHeight: 300, // maxHeight: 300,
overflow: 'auto', // overflow: 'auto',
}} // }}
placeholder="" placeholder=""
allowClear allowClear
treeDefaultExpandAll treeDefaultExpandAll
// onChange={onChange} onChange={(label, extra) => {
treeData={treeList || []} // console.log(label, extra);
/> }}
onSearch={v => {
// console.log(v);
}}
onSelect={(value, node, extra) => {
setRuleBasis(node.key)
}}
// treeData={treeList || []}
>
{treeList?.length && recursive(treeList)}
</TreeSelect>
</Form.Item> </Form.Item>
</Form> </Form>
</Modal > </Modal >

13
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) { if (name.filter(f => d.name == f.name)?.length) {
name.filter(f => d.name == f.name)?.forEach(s => { name.filter(f => d.name == f.name)?.forEach(s => {
s.number = s.number + 1 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 { } else {
name.push({ name: d.name, number: 0 }) name.push({ name: d.name, number: 0 })
@ -83,16 +83,23 @@ function Approve ({ loading, clientHeight, actions, dispatch, }) {
const zip = new JSZip() const zip = new JSZip()
let result = [] 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 => { fileUrl.map(d => {
let url = d?.url?.replace(/\\/g, '/') let url = d?.url?.replace(/\\/g, '/')
let promise = getFileBlob(url).then((res) => { 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) result.push(promise)
}) })
Promise.all(result).then(() => { Promise.all(result).then(() => {
zip.generateAsync({ type: "blob" }).then((res) => { zip.generateAsync({ type: "blob" }).then((res) => {
saveAs(res, `标准文档.zip`) saveAs(res, `标准文档.zip`);
}) })
}) })
} }

78
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: '' }
});
}

15
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' }
// });
// }

11
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,
}

52
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: '' }
});
}

118
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 <>
<Modal title="标准文档上传" open={true} width={600}
onOk={e => {
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()
}}
>
<Form
style={{ marginLeft: 20 }}
form={form}
onValuesChange={v => {
}}
autoComplete="off"
labelCol={{ span: 4 }} wrapperCol={{ span: 20 }}
>
<Form.Item label="标准类型" name="standardType" rules={[{ required: true, message: '请选择标准类型' }]}>
<Select style={{ width: 200, }} allowClear
options={[{ value: '国家标准', label: '国家标准', }, { value: '行业标准', label: '行业标准', }, { value: '地方标准', label: '地方标准', },]}
/>
</Form.Item>
<Form.Item label="标签" name="tags" >
<Input allowClear placeholder='请输入标签' maxLength={50} style={{ width: 300, marginRight: 16 }} />
</Form.Item>
<Form.Item
label='文件'
name='files'
key='files'
rules={[{ required: true, message: '文件不可为空' }]}>
<UploadLocal
// addNew={editData.add || !editData.record.files.length}
isLocal={true}
maxFilesNum={1}
maxFileSize={40}
onChange={vsjunct}
fileTypes={["jpg", "png", "gif", "txt", "doc", "docx", "pdf", "xls", "xlsx", "zip", "rar"]}
value={editUrl}
// fileList={editData.record.files || []}
/>
</Form.Item>
<Form.Item style={{ marginLeft: 42 }} key='tip'>
<Tag color="orange">文件大小不超过40MB开放资源包含多个文件建议将文件进行压缩形成压缩包再上传</Tag>
<Tag color="orange">支持的文件格式jpg,png,gif,txt,doc,docx,pdf,xsl,xlsx,zip,rar</Tag>
</Form.Item>
</Form>
</Modal >
</>
}
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)

66
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 <>
<Modal title="新建分组" open={true}
onOk={e => {
form.validateFields().then(v => {
dispatch(dataQuality.postStandardDocFolders({
...v,
parent: parent || null,
})).then(res => {
if (res.success) {
close()
success()
}
})
})
}}
onCancel={() => {
close()
}}
>
<Form
style={{ marginLeft: 20 }}
form={form}
onValuesChange={v => {
}}
autoComplete="off"
>
<Form.Item label="名称" name="name" rules={[{ required: true, message: '请输入分组名称,最多50字', max: 50 },]}>
<Input allowClear placeholder='请输入分组名称' style={{ width: 300, }} />
</Form.Item>
</Form>
</Modal >
</>
}
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)

104
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 <>
<Modal title={editData?.id ? '编辑业务规则' : "新建业务规则"} open={true}
onOk={e => {
form.validateFields().then(v => {
// console.log(v);
dispatch(dataQuality.postBusinessRules({
...v, id: editData?.id
})).then(res => {
if (res.success) {
close()
success()
}
})
})
}}
onCancel={() => {
close()
}}
>
<Form
style={{ marginLeft: 20 }}
form={form}
onValuesChange={v => {
}}
autoComplete="off"
labelCol={{ span: 4 }} wrapperCol={{ span: 20 }}
>
<Form.Item label="名称" name="name" initialValue={editData?.name} rules={[{ required: true, message: '请输入分组名称,最多50字', max: 50}]}>
<Input allowClear placeholder='请输入分组名称' style={{ width: 300 }} />
</Form.Item>
<Form.Item label="描述" name="description" initialValue={editData?.description} rules={[{ required: true, message: '请输入分组名称' }]}>
<TextArea allowClear autoSize={{ minRows: 2 }} placeholder='描述' style={{ width: 300, }} />
</Form.Item>
<Form.Item label="问题类型" name="problemType" initialValue={editData?.problemType} rules={[{ required: true, message: '请输入分组名称' }]}>
<Select style={{ width: 300, }} placeholder='问题类型'
options={[{ value: '一致性', label: '一致性', }, { value: '准确性', label: '准确性', }, { value: '完整性', label: '完整性', }, { value: '有效性', label: '有效性', }, { value: '及时性', label: '及时性', }, { value: '规范性', label: '规范性', },]}
/>
</Form.Item>
<Form.Item label="问题级别" name="problemLevel" initialValue={editData?.problemLevel} rules={[{ required: true, message: '请输入分组名称' }]}>
<Select style={{ width: 300, }} placeholder='问题级别'
options={[{ value: '一般', label: '一般', }, { value: '重要', label: '重要', }, { value: '严重', label: '严重', },]}
/>
</Form.Item>
<Form.Item label="制定依据" name="ruleBasis" initialValue={editData?.ruleBasis} rules={[{ required: true, message: '请输入分组名称' }]}>
<TreeSelect
showSearch
style={{
width: 300,
}}
// value={}
dropdownStyle={{
maxHeight: 300,
overflow: 'auto',
}}
placeholder=""
allowClear
treeDefaultExpandAll
// onChange={onChange}
treeData={treeList || []}
/>
</Form.Item>
</Form>
</Modal >
</>
}
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)

6
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};

160
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) => <div style={{ width: 126 }}>
<Button type="link" onClick={() => {
// setEditData(record)
// setRuleModal(true);
}}>查看详情</Button>
<Button type="link" onClick={() => {
// setEditData(record)
// setRuleModal(true);
}}>编辑</Button>
<Popconfirm
title="是否确认删除该业务规则?"
onConfirm={() => {
dispatch(dataQuality.delBusinessRules(record.id)).then(res => {
if (res.success) {
setQuery({ limit: 10, page: 0 });
resourceData({ limit: 10, page: 0, keyword })
}
})
}}
>
<Button type="link">删除</Button>
</Popconfirm>
<Button type="link" onClick={() => {
// setEditData(record)
// setRuleModal(true);
}}>禁用</Button>
</div>
},
];
return <>
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
<div style={{ display: 'flex', }}>
<Input
placeholder="接口名称"
value={keyword}
onChange={e => {
setKeyword(e?.target?.value)
}}
style={{
width: 266, marginRight: 10
}}
/>
<Button onClick={() => {
setQuery({ limit: 10, page: 0 });
resourceData({ limit: 10, page: 0, keyword })
}}>搜索</Button>
</div>
</div>
<Table
columns={columns}
dataSource={tableList?.rows || []}
scroll={{ scrollToFirstRowOnChange: true, y: clientHeight - 260 }}
pagination={{
current: query?.page + 1,
pageSize: query?.limit,
total: tableList?.count,
showSizeChanger: true,
// showQuickJumper: true,
showTotal: (total) => { return <span style={{ fontSize: 15 }}>{`${Math.ceil(total / query?.limit)}页,${total}`}</span> },
onChange: (page, pageSize) => {
setQuery({ limit: pageSize, page: page - 1 });
resourceData({ limit: pageSize, page: page - 1, keyword });
}
}}
/>
{
ruleModal ?
<RuleModal
treeList={treeList}
editData={editData}
close={() => {
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)

158
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) => <div style={{ width: 126 }}>
<Button type="link" onClick={() => {
// setEditData(record)
// setRuleModal(true);
}}>查看详情</Button>
<Button type="link" onClick={() => {
// setEditData(record)
// setRuleModal(true);
}}>编辑</Button>
<Popconfirm
title="是否确认删除该业务规则?"
onConfirm={() => {
dispatch(dataQuality.delBusinessRules(record.id)).then(res => {
if (res.success) {
setQuery({ limit: 10, page: 0 });
resourceData({ limit: 10, page: 0, keyword })
}
})
}}
>
<Button type="link">删除</Button>
</Popconfirm>
<Button type="link" onClick={() => {
// setEditData(record)
// setRuleModal(true);
}}>禁用</Button>
</div>
},
];
return <>
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
<div style={{ display: 'flex', }}>
<Input
placeholder="接口名称"
value={keyword}
onChange={e => {
setKeyword(e?.target?.value)
}}
style={{
width: 266, marginRight: 10
}}
/>
<Button onClick={() => {
setQuery({ limit: 10, page: 0 });
resourceData({ limit: 10, page: 0, keyword })
}}>搜索</Button>
</div>
</div>
<Table
columns={columns}
dataSource={tableList?.rows || []}
scroll={{ scrollToFirstRowOnChange: true, y: clientHeight - 260 }}
pagination={{
current: query?.page + 1,
pageSize: query?.limit,
total: tableList?.count,
showSizeChanger: true,
// showQuickJumper: true,
showTotal: (total) => { return <span style={{ fontSize: 15 }}>{`${Math.ceil(total / query?.limit)}页,${total}`}</span> },
onChange: (page, pageSize) => {
setQuery({ limit: pageSize, page: page - 1 });
resourceData({ limit: pageSize, page: page - 1, keyword });
}
}}
/>
{
ruleModal ?
<RuleModal
treeList={treeList}
editData={editData}
close={() => {
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)

15
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
};

19
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 (
<SubMenu key="dataService" icon={<CarryOutOutlined />} title='数据服务'>
<Menu.Item key="serviceManagement">
<Link to="/dataService/serviceManagement">服务管理</Link>
</Menu.Item>
<Menu.Item key="serviceView">
<Link to="/dataService/serviceView">服务查看</Link>
</Menu.Item>
</ SubMenu >
);
}

5
web/client/src/sections/dataService/reducers/index.js

@ -0,0 +1,5 @@
'use strict';
export default {
}

22
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: '服务查看'
}]
}
}];

9
web/client/src/sections/safetySpecification/containers/specificationLibrary.js

@ -60,10 +60,17 @@ function SpecificationLibrary ({ loading, clientHeight, actions, dispatch, }) {
function packBulk ({ fileUrl, folderId }) { function packBulk ({ fileUrl, folderId }) {
const zip = new JSZip() const zip = new JSZip()
let result = [] 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 => { fileUrl.map(d => {
let url = d?.url?.replace(/\\/g, '/') let url = d?.url?.replace(/\\/g, '/')
let promise = getFileBlob(url).then((res) => { 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) result.push(promise)
}) })

Loading…
Cancel
Save