Commit 53357dba by zhaochengxiang

主数据管理

parent e2abd806
...@@ -28,6 +28,7 @@ const EditModel = loadable(()=> import('./view/Manage/Model/Component/EditModel' ...@@ -28,6 +28,7 @@ const EditModel = loadable(()=> import('./view/Manage/Model/Component/EditModel'
const EditTemplate = loadable(()=> import('./view/Manage/ModelConfig/Component/EditTemplate')); const EditTemplate = loadable(()=> import('./view/Manage/ModelConfig/Component/EditTemplate'));
const AssetTree = loadable(()=> import('./view/Manage/AssetManage/Component/AssetManageTree')); const AssetTree = loadable(()=> import('./view/Manage/AssetManage/Component/AssetManageTree'));
const DataMasterDefine = loadable(()=> import('./view/Manage/DataMaster/Define')); const DataMasterDefine = loadable(()=> import('./view/Manage/DataMaster/Define'));
const DataMasterManage = loadable(()=> import('./view/Manage/DataMaster/Manage'));
export class App extends React.Component { export class App extends React.Component {
constructor() { constructor() {
...@@ -155,6 +156,7 @@ export class App extends React.Component { ...@@ -155,6 +156,7 @@ export class App extends React.Component {
<Route path={'/center-home/menu/asset-browse'} component={AssetBrowse} exact /> <Route path={'/center-home/menu/asset-browse'} component={AssetBrowse} exact />
<Route path={'/center-home/menu/asset-recycle'} component={AssetRecycle} exact /> <Route path={'/center-home/menu/asset-recycle'} component={AssetRecycle} exact />
<Route path={'/center-home/menu/data-master-define'} component={DataMasterDefine} exact /> <Route path={'/center-home/menu/data-master-define'} component={DataMasterDefine} exact />
<Route path={'/center-home/menu/data-master-manage'} component={DataMasterManage} exact />
<Route path={'/center-home/data-model-action'} component={EditModel} exact /> <Route path={'/center-home/data-model-action'} component={EditModel} exact />
<Route path={'/center-home/asset-detail'} component={AssetDetailPage} exact /> <Route path={'/center-home/asset-detail'} component={AssetDetailPage} exact />
</Switch> </Switch>
......
...@@ -5,21 +5,18 @@ import { useContextMenu, Menu as RcMenu, Item as RcItem } from "react-contexify" ...@@ -5,21 +5,18 @@ import { useContextMenu, Menu as RcMenu, Item as RcItem } from "react-contexify"
import ResizeableTable from '../../../ResizeableTable'; import ResizeableTable from '../../../ResizeableTable';
import DebounceInput from '../../../Model/Component/DebounceInput'; import DebounceInput from '../../../Model/Component/DebounceInput';
import { UpdateTemplateModal } from './UpdateTemplateModal'; import { UpdateTemplateModal } from './UpdateTemplateModal';
import UpdateDataMasterModal from './UpdateDataMasterModal';
import { inputWidth } from '../../../../../util'; import { inputWidth } from '../../../../../util';
import DataMasterExpandedTable from './DataMasterExpandedTable';
import { tableData } from './Mock'; import { tableData } from './Mock';
import './DataMasterTable.less'; import './DefineTable.less';
import 'react-contexify/dist/ReactContexify.css'; import 'react-contexify/dist/ReactContexify.css';
const InputDebounce = DebounceInput(300)(Input); const InputDebounce = DebounceInput(300)(Input);
const DataMasterTable = (props) => { const DefineTable = (props) => {
const [keyword, setKeyword] = useState(''); const [keyword, setKeyword] = useState('');
const [checkedKeys, setCheckedKeys] = useState([]); const [checkedKeys, setCheckedKeys] = useState([]);
const [isTemplateModalVisible, setIsTemplateModalVisible] = useState(false); const [isTemplateModalVisible, setIsTemplateModalVisible] = useState(false);
const [isDataMasterModalVisible, setIsDataMasterModalVisible] = useState(false);
const [currentTemplate, setCurrentTemplate] = useState({}); const [currentTemplate, setCurrentTemplate] = useState({});
const [action, setAction] = useState(''); const [action, setAction] = useState('');
...@@ -110,18 +107,12 @@ const DataMasterTable = (props) => { ...@@ -110,18 +107,12 @@ const DataMasterTable = (props) => {
const handleItemClick = ({ event, props, data, triggerEvent }) => { const handleItemClick = ({ event, props, data, triggerEvent }) => {
const key = event.currentTarget.id; const key = event.currentTarget.id;
if (key === 'add') { if (key === 'update') {
setIsDataMasterModalVisible(true);
} else if (key === 'update') {
setAction('update'); setAction('update');
setIsTemplateModalVisible(true); setIsTemplateModalVisible(true);
} }
} }
const onDataMasterModalCancel = () => {
setIsDataMasterModalVisible(false);
}
const rowSelection = { const rowSelection = {
selectedRowKeys: checkedKeys, selectedRowKeys: checkedKeys,
onChange: onTableSelectChange, onChange: onTableSelectChange,
...@@ -152,11 +143,6 @@ const DataMasterTable = (props) => { ...@@ -152,11 +143,6 @@ const DataMasterTable = (props) => {
rowSelection={rowSelection} rowSelection={rowSelection}
columns={columns} columns={columns}
dataSource={tableData} dataSource={tableData}
pagination={false}
expandable={{
expandedRowRender: record => <DataMasterExpandedTable />,
rowExpandable: record => true,
}}
onRow={(record) => { onRow={(record) => {
return { return {
onContextMenu: event => { onContextMenu: event => {
...@@ -165,6 +151,7 @@ const DataMasterTable = (props) => { ...@@ -165,6 +151,7 @@ const DataMasterTable = (props) => {
}, },
}; };
}} }}
pagination={false}
scroll={{ y: 'calc(100vh - 94px - 37px - 57px - 24px - 32px)' }} scroll={{ y: 'calc(100vh - 94px - 37px - 57px - 24px - 32px)' }}
/> />
</div> </div>
...@@ -175,16 +162,7 @@ const DataMasterTable = (props) => { ...@@ -175,16 +162,7 @@ const DataMasterTable = (props) => {
onCancel={onTemplateModalCancel} onCancel={onTemplateModalCancel}
/> />
<UpdateDataMasterModal
visible={isDataMasterModalVisible}
template={currentTemplate}
onCancel={onDataMasterModalCancel}
/>
<RcMenu id={MENU_ID}> <RcMenu id={MENU_ID}>
<RcItem id="add" onClick={handleItemClick}>
新增主数据
</RcItem>
<RcItem id="update" onClick={handleItemClick}> <RcItem id="update" onClick={handleItemClick}>
编辑 编辑
</RcItem> </RcItem>
...@@ -193,4 +171,4 @@ const DataMasterTable = (props) => { ...@@ -193,4 +171,4 @@ const DataMasterTable = (props) => {
); );
} }
export default DataMasterTable; export default DefineTable;
\ No newline at end of file \ No newline at end of file
...@@ -5,11 +5,11 @@ import {PlusOutlined, ReloadOutlined} from '@ant-design/icons'; ...@@ -5,11 +5,11 @@ import {PlusOutlined, ReloadOutlined} from '@ant-design/icons';
import {highlightSearchContentByTerms} from '../../../../../util'; import {highlightSearchContentByTerms} from '../../../../../util';
import {treeData} from './Mock'; import {treeData} from './Mock';
import './DataMasterTree.less'; import './DefineTree.less';
const {Option} = AutoComplete; const {Option} = AutoComplete;
const DataMasterTree = (props) => { const DefineTree = (props) => {
const {onClick} = props; const {onClick} = props;
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [options, setOptions] = useState([]); const [options, setOptions] = useState([]);
...@@ -152,4 +152,4 @@ const DataMasterTree = (props) => { ...@@ -152,4 +152,4 @@ const DataMasterTree = (props) => {
); );
} }
export default DataMasterTree; export default DefineTree;
\ No newline at end of file \ No newline at end of file
import { Form, Input, Divider, Row, Col, Descriptions } from "antd"; import { Form, Input, Row, Col, Descriptions } from "antd";
const { TextArea } = Input; const { TextArea } = Input;
......
...@@ -3,13 +3,13 @@ import { Tooltip, Table, Space, Popover, Input, Button, Form } from "antd"; ...@@ -3,13 +3,13 @@ import { Tooltip, Table, Space, Popover, Input, Button, Form } from "antd";
import { QuestionCircleOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons'; import { QuestionCircleOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons';
import { useClickAway } from 'ahooks'; import { useClickAway } from 'ahooks';
import update from 'immutability-helper'; import update from 'immutability-helper';
import { DndProvider, useDrag, useDrop } from 'react-dnd'; import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend'; import { HTML5Backend } from 'react-dnd-html5-backend';
import DebounceInput from "../../../Model/Component/DebounceInput"; import DebounceInput from "../../../Model/Component/DebounceInput";
import { templateFileds } from "./Mock"; import { templateFileds } from "./Mock";
import { inputWidth, generateUUID } from "../../../../../util"; import { inputWidth, generateUUID } from "../../../../../util";
import { DatatypeInput, EditableCell, DragableBodyRow } from "../../../Model/Component/ImportActionTable"; import { EditableCell, DragableBodyRow } from "../../../Model/Component/ImportActionTable";
import { dispatch } from "../../../../../model"; import { dispatch } from "../../../../../model";
import { EditTemplateContext } from "./UpdateTemplateModal"; import { EditTemplateContext } from "./UpdateTemplateModal";
......
...@@ -3,10 +3,10 @@ import classNames from 'classnames'; ...@@ -3,10 +3,10 @@ import classNames from 'classnames';
import { ResizableBox } from 'react-resizable'; import { ResizableBox } from 'react-resizable';
import { CaretLeftOutlined, CaretRightOutlined } from '@ant-design/icons'; import { CaretLeftOutlined, CaretRightOutlined } from '@ant-design/icons';
import DataMasterTree from './Component/DataMasterTree'; import DefineTree from './Component/DefineTree';
import DefineTable from './Component/DefineTable';
import './index.less'; import './index.less';
import DataMasterTable from './Component/DataMasterTable';
const DataMasterDefine = (props) => { const DataMasterDefine = (props) => {
...@@ -31,7 +31,7 @@ const DataMasterDefine = (props) => { ...@@ -31,7 +31,7 @@ const DataMasterDefine = (props) => {
axis='x' axis='x'
minConstraints={[230, Infinity]} maxConstraints={[Infinity, Infinity]} minConstraints={[230, Infinity]} maxConstraints={[Infinity, Infinity]}
> >
<DataMasterTree /> <DefineTree />
</ResizableBox> </ResizableBox>
<div className='left-collapse-wrap'> <div className='left-collapse-wrap'>
<div className='left-collapse' onClick={onCollapseClick}> <div className='left-collapse' onClick={onCollapseClick}>
...@@ -39,7 +39,7 @@ const DataMasterDefine = (props) => { ...@@ -39,7 +39,7 @@ const DataMasterDefine = (props) => {
</div> </div>
</div> </div>
<div className='right-wrap'> <div className='right-wrap'>
<DataMasterTable /> <DefineTable />
</div> </div>
</div> </div>
) )
......
import { useMemo } from 'react'; import { useMemo, useState } from 'react';
import { Space, Button, Input } from 'antd';
import { useContextMenu, Menu as RcMenu, Item as RcItem } from "react-contexify";
import ResizeableTable from '../../../ResizeableTable'; import ResizeableTable from '../../../ResizeableTable';
import { expandedTableData } from './Mock'; import DebounceInput from '../../../Model/Component/DebounceInput';
import UpdateDataMasterModal from './UpdateDataMasterModal';
import { inputWidth } from '../../../../../util';
import { expandedTableData } from '../../Define/Component/Mock';
import '../../Define/Component/DefineTable.less';
import 'react-contexify/dist/ReactContexify.css';
const InputDebounce = DebounceInput(300)(Input);
const ManageTable = (props) => {
const [keyword, setKeyword] = useState('');
const [checkedKeys, setCheckedKeys] = useState([]);
const [isDataMasterModalVisible, setIsDataMasterModalVisible] = useState(false);
const [currentTemplate, setCurrentTemplate] = useState({});
const [action, setAction] = useState('');
const DataMasterExpandedTable = (props) => {
const columns = useMemo(() => { const columns = useMemo(() => {
return ([ return ([
{ {
...@@ -53,16 +69,103 @@ const DataMasterExpandedTable = (props) => { ...@@ -53,16 +69,103 @@ const DataMasterExpandedTable = (props) => {
}, },
]); ]);
}, []); }, []);
const MENU_ID = 'data-master-manage-table-contextmenu';
const { show } = useContextMenu({
id: MENU_ID,
});
const onAddClick = () => {
setAction('add');
setIsDataMasterModalVisible(true);
}
const onItemClick = () => {
setAction('detail');
setIsDataMasterModalVisible(true);
}
const onDataMasterModalCancel = () => {
setIsDataMasterModalVisible(false);
}
const onBatchDeleteClick = () => {
}
const onSearchInputChange = (value) => {
setKeyword(value);
}
const onTableSelectChange = keys => {
setCheckedKeys(keys);
};
const handleItemClick = ({ event, props, data, triggerEvent }) => {
const key = event.currentTarget.id;
if (key === 'update') {
setAction('update');
setIsDataMasterModalVisible(true);
}
}
const rowSelection = {
selectedRowKeys: checkedKeys,
onChange: onTableSelectChange,
};
return ( return (
<div className='p-1'> <div className='data-master-table'>
<div className='data-master-header px-3'>
<Space>
<Space>
<Button onClick={onAddClick}>新建</Button>
</Space>
<Space>
<Button onClick={onBatchDeleteClick}>删除</Button>
</Space>
</Space>
<InputDebounce
placeholder="通过主数据模版名称搜索"
allowClear
value={keyword}
onChange={onSearchInputChange}
style={{ width: inputWidth, marginLeft: 'auto' }}
/>
</div>
<div className='data-master-content p-3'>
<ResizeableTable <ResizeableTable
rowKey='id' rowKey='id'
rowSelection={rowSelection}
columns={columns} columns={columns}
dataSource={expandedTableData} dataSource={expandedTableData}
onRow={(record) => {
return {
onContextMenu: event => {
setCurrentTemplate(record);
show(event);
},
};
}}
pagination={false} pagination={false}
scroll={{ y: 'calc(100vh - 94px - 37px - 57px - 24px - 32px)' }}
/> />
</div> </div>
<UpdateDataMasterModal
action={action}
visible={isDataMasterModalVisible}
onCancel={onDataMasterModalCancel}
/>
<RcMenu id={MENU_ID}>
<RcItem id="update" onClick={handleItemClick}>
编辑
</RcItem>
</RcMenu>
</div>
); );
} }
export default DataMasterExpandedTable; export default ManageTable;
\ No newline at end of file \ No newline at end of file
import {useEffect, useMemo, useState} from 'react';
import {Tooltip, Spin, AutoComplete, Tree} from 'antd';
import {PlusOutlined, ReloadOutlined} from '@ant-design/icons';
import {highlightSearchContentByTerms} from '../../../../../util';
import {treeData} from '../../Define/Component/Mock';
import '../../Define/Component/DefineTree.less';
const {Option} = AutoComplete;
const ManageTree = (props) => {
const {onClick} = props;
const [loading, setLoading] = useState(false);
const [options, setOptions] = useState([]);
const [keyword, setKeyword] = useState('');
const [expandedKeys, setExpandedKeys] = useState(['0-0']);
const [selectedKeys, setSelectedKeys] = useState(['0-0']);
const [autoExpandParent, setAutoExpandParent] = useState(false);
useEffect(() => {
setLoading(false);
onTreeSelect(['0-0']);
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
const treeList = useMemo(() => {
const generateList = (data, list, path = null) => {
for (let i = 0; i < data.length; i++) {
const node = data[i];
const { key, title } = node;
const currentPath = path ? `${path}/${title}` : title;
list.push({ key, title: currentPath });
if (node.children) {
generateList(node.children, list, currentPath);
}
}
};
const newTreeList = [];
generateList(treeData, newTreeList);
return newTreeList;
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [treeData])
const onAddClick = () => {
}
const onRefreshClick = () => {
}
const onAutoCompleteSearch = (searchText) => {
setKeyword(searchText);
setOptions(treeList.filter(item => item.title.indexOf(searchText)!==-1));
};
const onAutoCompleteSelect = (value, option) => {
const paths = value.split('/');
setKeyword(paths[paths.length-1]);
onTreeSelect([option.key]);
setExpandedKeys(Array.from(new Set([...expandedKeys, option.key])));
setAutoExpandParent(true);
};
const onAutoCompleteClear = () => {
setKeyword('');
}
const onTreeExpand = (expandedKeys) => {
setExpandedKeys(expandedKeys);
setAutoExpandParent(false);
}
const onTreeSelect = (selectedKeys) => {
if (selectedKeys.length === 0) {
return;
}
setSelectedKeys(selectedKeys);
onClick && onClick(selectedKeys[0]);
}
return (
<div className='data-master-tree'>
<div className='header p-3'>
<Tooltip title="新增目录">
<PlusOutlined
className='default'
onClick={onAddClick}
style={{
fontSize:16,
cursor:'pointer',
flex: 1
}}
/>
</Tooltip>
<Tooltip title="刷新目录" className='ml-2'>
<ReloadOutlined
className='default'
onClick={onRefreshClick}
style={{
fontSize:16,
cursor:'pointer',
flex: 1
}}
/>
</Tooltip>
<div style={{flex: 3}} />
</div>
<div className='content p-3'>
<Spin spinning={loading}>
<AutoComplete
className='content-search'
allowClear
value={keyword}
onSelect={onAutoCompleteSelect}
onSearch={onAutoCompleteSearch}
onClear={onAutoCompleteClear}
>
{
(options||[]).map((item, index) => {
return (
<Option key={item.key} value={item.title}>
<div style={{ whiteSpace: 'normal' }}>
{highlightSearchContentByTerms(item.title, [keyword])}
</div>
</Option>
);
})
}
</AutoComplete>
<Tree
className='content-tree'
showLine
showIcon={false}
autoExpandParent={autoExpandParent}
treeData={treeData}
onExpand={onTreeExpand}
onSelect={onTreeSelect}
expandedKeys={expandedKeys}
selectedKeys={selectedKeys}
/>
</Spin>
</div>
</div>
);
}
export default ManageTree;
\ No newline at end of file
import { Modal, Form, Input } from "antd"; import { Modal, Form, Input } from "antd";
import { attrs } from "./Mock"; import { attrs } from "../../Define/Component/Mock";
import './UpdateDataMasterModal.less'; import './UpdateDataMasterModal.less';
const UpdateTemplateModal = (props) => { const UpdateDataMasterModal = (props) => {
const {visible, onCancel, template} = props; const {visible, onCancel} = props;
const [form] = Form.useForm(); const [form] = Form.useForm();
const formItemLayout = { const formItemLayout = {
...@@ -54,4 +54,4 @@ const UpdateTemplateModal = (props) => { ...@@ -54,4 +54,4 @@ const UpdateTemplateModal = (props) => {
); );
} }
export default UpdateTemplateModal; export default UpdateDataMasterModal;
\ No newline at end of file \ No newline at end of file
import { useMemo, useState } from 'react';
import classNames from 'classnames';
import { ResizableBox } from 'react-resizable';
import { CaretLeftOutlined, CaretRightOutlined } from '@ant-design/icons';
import ManageTree from './Component/ManageTree';
import ManageTable from './Component/ManageTable';
import '../Define/index.less';
const DataMasterManage = (props) => {
const [collapse, setCollapse] = useState(false);
const classes = useMemo(() => {
return classNames('data-master', {
'data-master-collapse': collapse,
});
}, [collapse]);
const onCollapseClick = () => {
setCollapse(!collapse);
}
return (
<div className={classes}>
<ResizableBox
className='left-wrap'
width={230}
height={Infinity}
axis='x'
minConstraints={[230, Infinity]} maxConstraints={[Infinity, Infinity]}
>
<ManageTree />
</ResizableBox>
<div className='left-collapse-wrap'>
<div className='left-collapse' onClick={onCollapseClick}>
{ collapse ? <CaretRightOutlined /> : <CaretLeftOutlined /> }
</div>
</div>
<div className='right-wrap'>
<ManageTable />
</div>
</div>
)
}
export default DataMasterManage;
\ No newline at end of file
...@@ -13,6 +13,7 @@ import AssetResourceBrowse from './AssetResourceBrowse'; ...@@ -13,6 +13,7 @@ import AssetResourceBrowse from './AssetResourceBrowse';
import AssetBrowse from './AssetBrowse'; import AssetBrowse from './AssetBrowse';
import AssetRecycle from './AssetRecycle'; import AssetRecycle from './AssetRecycle';
import DataMasterDefine from "./DataMaster/Define"; import DataMasterDefine from "./DataMaster/Define";
import DataMasterManage from "./DataMaster/Manage";
class Manage extends Component { class Manage extends Component {
...@@ -35,6 +36,7 @@ class Manage extends Component { ...@@ -35,6 +36,7 @@ class Manage extends Component {
<Route path={`${match.path}/asset-browse`} component={AssetBrowse} /> <Route path={`${match.path}/asset-browse`} component={AssetBrowse} />
<Route path={`${match.path}/asset-recycle`} component={AssetRecycle} /> <Route path={`${match.path}/asset-recycle`} component={AssetRecycle} />
<Route path={`${match.path}/data-master-define`} component={DataMasterDefine} /> <Route path={`${match.path}/data-master-define`} component={DataMasterDefine} />
<Route path={`${match.path}/data-master-manage`} component={DataMasterManage} />
</Switch> </Switch>
) : ( ) : (
<GetSession {...this.props} /> <GetSession {...this.props} />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment