zmh
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 React, { useEffect, useState } from 'react'; |
||||
import { connect } from 'react-redux'; |
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 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(() => { |
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 <>最新元数据 |
const setTreeNodeTitle = (name) => { |
||||
<Button type="primary" onClick={() => { history.push(`/metadataManagement/latestMetadata/detail/${1}`) }} >查看详情</Button> |
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) { |
function mapStateToProps(state) { |
||||
const { global, auth } = state; |
const { global, auth, resourceCatalog } = state; |
||||
return { |
return { |
||||
clientHeight: global.clientHeight, |
|
||||
user: auth.user, |
user: auth.user, |
||||
actions: global.actions, |
actions: global.actions, |
||||
|
clientHeight: global.clientHeight, |
||||
|
resourceCatalog: resourceCatalog?.data || [], |
||||
|
isRequesting: resourceCatalog.isRequesting |
||||
}; |
}; |
||||
} |
} |
||||
export default connect(mapStateToProps)(LatestMetadata) |
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