peng.peng
2 years ago
9 changed files with 325 additions and 27 deletions
@ -0,0 +1,53 @@ |
|||
'use strict'; |
|||
|
|||
import { basicAction } from '@peace/utils' |
|||
import { ApiTable } from '$utils' |
|||
|
|||
export function getResourceCatalog(params) { |
|||
return dispatch => basicAction({ |
|||
type: 'get', |
|||
dispatch: dispatch, |
|||
query: params, |
|||
actionType: 'GET_RESOURCE_CATALOG', |
|||
url: ApiTable.getResourceCatalog, |
|||
msg: { error: '获取资源目录失败' }, |
|||
reducer: { name: 'resourceCatalog' } |
|||
}); |
|||
} |
|||
|
|||
export function postResourceCatalog(data) { |
|||
return dispatch => basicAction({ |
|||
type: 'post', |
|||
data: data, |
|||
dispatch: dispatch, |
|||
actionType: 'POST_RESOURCE_CATALOG', |
|||
url: ApiTable.postResourceCatalog, |
|||
msg: { option: '新增资源目录' }, |
|||
reducer: {} |
|||
}); |
|||
} |
|||
|
|||
export function putResourceCatalog(id, data) { |
|||
return dispatch => basicAction({ |
|||
type: 'put', |
|||
data: data, |
|||
dispatch, |
|||
actionType: 'PUT_RESOURCE_CATALOG', |
|||
url: ApiTable.putResourceCatalog.replace('{id}', id), |
|||
msg: { |
|||
option: '修改资源目录', |
|||
} |
|||
}); |
|||
} |
|||
|
|||
export function delResourceCatalog(id) { |
|||
return dispatch => basicAction({ |
|||
type: 'del', |
|||
dispatch, |
|||
actionType: 'DELETE_RESOURCE_CATALOG', |
|||
url: ApiTable.delResourceCatalog.replace('{id}', id), |
|||
msg: { |
|||
option: '删除资源目录', |
|||
} |
|||
}); |
|||
} |
@ -0,0 +1,86 @@ |
|||
import React, { useEffect, useState } from 'react'; |
|||
import { Modal, Input, Form, message } from 'antd'; |
|||
const { TextArea } = Input; |
|||
const ResourceCatalogModal = (props) => { |
|||
const { resourceCatalog, onConfirm, onCancel, editData } = props; |
|||
const [form] = Form.useForm(); |
|||
useEffect(() => { |
|||
}, []); |
|||
const handleOk = () => { |
|||
form.validateFields().then(values => { |
|||
if (onConfirm) { |
|||
if (editData.add) { |
|||
//新建
|
|||
let exist = resourceCatalog.find(rc => rc.name === values.name); |
|||
if (exist) { |
|||
message.error('该资源目录名称已存在'); |
|||
return false; |
|||
} |
|||
exist = resourceCatalog.find(rc => rc.code === values.code); |
|||
if (exist) { |
|||
message.error('该资源目录代码已存在'); |
|||
return false; |
|||
} |
|||
} else {//修改
|
|||
let exist = resourceCatalog.find(rc => rc.name === values.name && rc.id != editData.record.id); |
|||
if (exist) { |
|||
message.error('该资源目录名称已存在'); |
|||
return false; |
|||
} |
|||
exist = resourceCatalog.find(rc => rc.code === values.code && rc.id != editData.record.id); |
|||
if (exist) { |
|||
message.error('该资源目录代码已存在'); |
|||
return false; |
|||
} |
|||
} |
|||
onConfirm(values) |
|||
} |
|||
}) |
|||
} |
|||
const validatorNull = (rule, value, getFieldValue, validateFields) => { |
|||
if (!value || !value.trim().length) { |
|||
return Promise.reject(new Error(`${rule.field === 'name' ? '名称' : '代码'}不可空字符串`)); |
|||
} |
|||
return Promise.resolve(); |
|||
} |
|||
return ( |
|||
<Modal title={editData.title} visible={true} destroyOnClose |
|||
okText='确定' width={800} |
|||
onOk={() => handleOk(null)} |
|||
onCancel={onCancel}> |
|||
<Form form={form} labelCol={{ span: 6 }} wrapperCol={{ span: 18 }} initialValues={editData.record || {}}> |
|||
{editData.child ? <Form.Item |
|||
label='上级目录' |
|||
name='parentName' |
|||
> |
|||
<Input disabled style={{ width: '90%' }} /> |
|||
</Form.Item> : null} |
|||
<Form.Item |
|||
label='名称' |
|||
name='name' |
|||
rules={[{ required: true, message: '' }, { max: 50, message: `名称不超过50个字符` }, |
|||
({ getFieldValue, validateFields }) => ({ |
|||
validator(_, value) { return validatorNull(_, value, getFieldValue, validateFields) } |
|||
})]}> |
|||
<Input style={{ width: '90%' }} placeholder={`请输入名称`} /> |
|||
</Form.Item> |
|||
<Form.Item |
|||
label='代码' |
|||
name='code' |
|||
rules={[{ required: true, message: '' }, { max: 50, message: `代码不超过50个字符` }, |
|||
({ getFieldValue, validateFields }) => ({ |
|||
validator(_, value) { return validatorNull(_, value, getFieldValue, validateFields) } |
|||
})]}> |
|||
<Input style={{ width: '90%' }} placeholder={`请输入代码`} /> |
|||
</Form.Item> |
|||
<Form.Item |
|||
label='描述' |
|||
name='description' |
|||
rules={[{ max: 255, message: `描述不超过255个字符` }]}> |
|||
<TextArea rows={4} style={{ width: '90%' }} placeholder={`请输入描述`} /> |
|||
</Form.Item> |
|||
</Form> |
|||
</Modal> |
|||
) |
|||
} |
|||
export default ResourceCatalogModal; |
@ -1,24 +1,160 @@ |
|||
import React, { useEffect, useState } from 'react'; |
|||
import { connect } from 'react-redux'; |
|||
import { Button, } from 'antd' |
|||
import { Spin, Row, Col, Tree, Button, Tooltip, Popconfirm } from 'antd'; |
|||
import { PlusCircleOutlined, EditOutlined, MinusCircleOutlined } from '@ant-design/icons'; |
|||
import theStyle from './style.css'; |
|||
import ResourceCatalogModal from '../components/resourceCatalogModal'; |
|||
let expandedKeysData = []; |
|||
|
|||
const LatestMetadata = (props) => { |
|||
const { user, dispatch, actions, history } = props; |
|||
const { user, dispatch, actions, clientHeight, resourceCatalog, isRequesting } = props; |
|||
const { metadataManagement } = actions; |
|||
const [resourceCatalogData, setResourceCatalogData] = useState([]); |
|||
const [selectedKeys, setSelectedKeys] = useState([]); |
|||
const [expandedKeys, setExpandedKeys] = useState([]); |
|||
const [modalVisible, setModalVisible] = useState(false); |
|||
const [editData, setEditData] = useState({}); |
|||
|
|||
useEffect(() => { |
|||
initData(true); |
|||
}, []) |
|||
const initData = (configRefresh) => { |
|||
dispatch(metadataManagement.getResourceCatalog()).then(res => { |
|||
const { data } = res.payload; |
|||
if (res.success) { |
|||
const resourceCatalogData = getTreeNodeData(data, null, 'rc'); |
|||
setResourceCatalogData(resourceCatalogData); |
|||
if (data.length) { |
|||
if (configRefresh) { |
|||
setExpandedKeys(expandedKeysData); |
|||
setSelectedKeys(expandedKeysData); |
|||
} |
|||
} else { |
|||
setExpandedKeys([]); |
|||
setSelectedKeys([]); |
|||
}; |
|||
} |
|||
}) |
|||
} |
|||
const getTreeNodeData = (dataSource, parent, key) => { |
|||
let treeData = []; |
|||
let data = []; |
|||
if (!parent) { |
|||
data = dataSource.filter(ds => !ds.parent); |
|||
if (!expandedKeysData.length && data.length) { |
|||
expandedKeysData.push(`rc-${data[0].id}`); |
|||
} |
|||
} else { |
|||
data = dataSource.filter(ds => ds.parent == parent); |
|||
} |
|||
treeData = data.map(ds => { |
|||
return { title: renderTreeNode(ds, dataSource), key: `${key}-${ds.id}`, id: ds.id } |
|||
}); |
|||
for (let d of treeData) { |
|||
d.children = getTreeNodeData(dataSource, d.id, d.key); |
|||
} |
|||
return treeData |
|||
} |
|||
|
|||
return <>最新元数据 |
|||
<Button type="primary" onClick={() => { history.push(`/metadataManagement/latestMetadata/detail/${1}`) }} >查看详情</Button> |
|||
</> |
|||
} |
|||
const setTreeNodeTitle = (name) => { |
|||
let content = <span>{name}</span> |
|||
if (name.length > 10) { |
|||
content = <Tooltip title={name}> |
|||
{name.substring(0, 10) + '...'} |
|||
</Tooltip> |
|||
} |
|||
return content; |
|||
} |
|||
|
|||
const renderTreeNode = (ds, dataSource) => { |
|||
return <div className={theStyle.icon}> |
|||
{setTreeNodeTitle(ds.name)} |
|||
<EditOutlined title='修改' style={{ marginLeft: 10 }} className={theStyle.tip} onClick={() => { |
|||
let record = JSON.parse(JSON.stringify(ds)); |
|||
let parentData = dataSource.filter(rc => rc.id === record.parent); |
|||
record.parentName = parentData.length ? parentData[0].name : ''; |
|||
setEditData({ record: record, title: '修改子类', child: ds.parent ? true : false, }); |
|||
setModalVisible(true); |
|||
}} /> |
|||
<Popconfirm placement="top" title={'确定删除该资源目录吗?'} onConfirm={() => { |
|||
dispatch(metadataManagement.delResourceCatalog(ds.id)).then((res) => { |
|||
if (res.success) { |
|||
expandedKeysData = []; initData(true); |
|||
} |
|||
setModalVisible(false); |
|||
}); |
|||
}} okText="确定" cancelText="取消"> |
|||
<MinusCircleOutlined title='删除' style={{ marginLeft: 10 }} className={theStyle.tip} /> |
|||
</Popconfirm> |
|||
<PlusCircleOutlined title='新建' style={{ marginLeft: 10 }} className={theStyle.tip} onClick={() => { |
|||
setEditData({ record: { parent: ds.id, parentName: ds.name }, title: '新建子类', child: true, add: true }); |
|||
setModalVisible(true); |
|||
}} /> |
|||
</div > |
|||
}; |
|||
//新建、修改
|
|||
const onConfirm = (values) => { |
|||
let obj = { ...values } |
|||
if (editData.add) { |
|||
obj = { ...values, ...editData.record || {} } |
|||
dispatch(metadataManagement.postResourceCatalog(obj)).then(() => { |
|||
initData(); setModalVisible(false); |
|||
}); |
|||
} else { |
|||
dispatch(metadataManagement.putResourceCatalog(editData.record.id, obj)).then(() => { |
|||
initData(); setModalVisible(false); |
|||
}); |
|||
} |
|||
} |
|||
return <Spin spinning={isRequesting}> |
|||
<Row> |
|||
<Col style={{ width: 240 }}> |
|||
<Button type='primary' style={{ marginBottom: 16 }} onClick={() => { |
|||
setEditData({ title: '新建资源目录', add: true }); |
|||
setModalVisible(true); |
|||
}}>新建资源目录</Button> |
|||
<Tree |
|||
// showLine
|
|||
height={clientHeight - 180} |
|||
expandedKeys={expandedKeys} |
|||
selectedKeys={selectedKeys} |
|||
onSelect={(keys, e) => { |
|||
if (e.selected) { |
|||
// setCurrentPage(1);
|
|||
setSelectedKeys(keys); |
|||
// let keyArr = allTreeNodeKeys.filter(ak => ak.key.includes(keys[0]));
|
|||
// let ids = keyArr.map(key => key.id);
|
|||
// console.log('all-' + JSON.stringify(ids))
|
|||
} |
|||
}} |
|||
onExpand={(keys) => { |
|||
setExpandedKeys(keys); |
|||
}} |
|||
treeData={resourceCatalogData} |
|||
/> |
|||
</Col> |
|||
<Col style={{ width: 'calc(100% - 240px)' }}> |
|||
|
|||
</Col> |
|||
</Row> |
|||
{ |
|||
modalVisible ? |
|||
<ResourceCatalogModal |
|||
resourceCatalog={resourceCatalog} |
|||
editData={editData} |
|||
onCancel={() => setModalVisible(false)} |
|||
onConfirm={onConfirm} /> : '' |
|||
} |
|||
</Spin> |
|||
} |
|||
function mapStateToProps(state) { |
|||
const { global, auth } = state; |
|||
const { global, auth, resourceCatalog } = state; |
|||
return { |
|||
clientHeight: global.clientHeight, |
|||
user: auth.user, |
|||
actions: global.actions, |
|||
clientHeight: global.clientHeight, |
|||
resourceCatalog: resourceCatalog?.data || [], |
|||
isRequesting: resourceCatalog.isRequesting |
|||
}; |
|||
} |
|||
export default connect(mapStateToProps)(LatestMetadata) |
@ -0,0 +1,16 @@ |
|||
.icon .tip { |
|||
margin-left: 10px; |
|||
-webkit-transition: opacity 0.1s 0.2s; |
|||
opacity: 0; |
|||
pointer-events: none; |
|||
} |
|||
|
|||
.icon:hover .tip { |
|||
-webkit-transition: opacity 0.2s; |
|||
opacity: 1; |
|||
pointer-events: auto; |
|||
} |
|||
|
|||
.icon .tip:hover { |
|||
-webkit-transition: none; |
|||
} |
Loading…
Reference in new issue