Commit 1bfe76cb by zhaochengxiang

个人自定义目录

parent ef8f942f
......@@ -64,6 +64,11 @@ export function* getDataAssetDetail(payload) {
export function* listDataAssetsByPage(payload) {
return yield call(service.listDataAssetsByPage, payload);
}
export function* listDataAssetsByPersonalCustomType(payload) {
return yield call(service.listDataAssetsByPersonalCustomType, payload);
}
export function* listRecycleBinDataAssetsByPage(payload) {
return yield call(service.listRecycleBinDataAssetsByPage, payload);
}
......@@ -97,10 +102,18 @@ export function* previewTreeByCustomElements(payload) {
return yield call(service.previewTreeByCustomElements, payload);
}
export function* previewTreeByCustomElementsAndResourceType(payload) {
return yield call(service.previewTreeByCustomElementsAndResourceType, payload);
}
export function* saveTreeByCustomElements(payload) {
return yield call(service.saveTreeByCustomElements, payload);
}
export function* saveTreeByCustomElementsAndResourceType(payload) {
return yield call(service.saveTreeByCustomElementsAndResourceType, payload);
}
export function* assetImport(payload) {
return yield call(service.assetImport, payload);
}
......@@ -121,6 +134,10 @@ export function* getDirectoryChild(payload) {
return yield call(service.getDirectoryChild, payload);
}
export function* getPersonalCustomDirecotryChild(payload) {
return yield call(service.getPersonalCustomDirecotryChild, payload);
}
export function* loadDataAssets(payload) {
return yield call(service.loadDataAssets, payload);
}
......
......@@ -64,6 +64,10 @@ export function listDataAssetsByPage(payload) {
return GetJSON("/dataassetmanager/dataAssetApi/listDataAssetsByPage", payload);
}
export function listDataAssetsByPersonalCustomType(payload) {
return GetJSON("/dataassetmanager/dataAssetApi/listDataAssetsByPersonalCustomType", payload);
}
export function listRecycleBinDataAssetsByPage(payload) {
return GetJSON("/dataassetmanager/dataAssetApi/listRecycleBinDataAssetsByPage", payload);
}
......@@ -132,10 +136,18 @@ export function previewTreeByCustomElements(payload) {
return PostJSON("/dataassetmanager/directoryApi/previewAsTreeByCustomElements", payload);
}
export function previewTreeByCustomElementsAndResourceType(payload) {
return PostJSON("/dataassetmanager/directoryApi/previewAsTreeByCustomElementsAndResourceType", payload);
}
export function saveTreeByCustomElements(payload) {
return PostJSON("/dataassetmanager/directoryApi/saveCustomElementTree", payload);
}
export function saveTreeByCustomElementsAndResourceType(payload) {
return PostJSON("/dataassetmanager/directoryApi/savePersonalCustomElementTreeByResourceType", payload);
}
export function assetImport(payload) {
return PostFile("/dataassetmanager/dataAssetApi/import", payload);
}
......@@ -156,6 +168,10 @@ export function getDirectoryChild(payload) {
return GetJSON("/dataassetmanager/directoryApi/getChildByParentId", payload);
}
export function getPersonalCustomDirecotryChild(payload) {
return GetJSON("/dataassetmanager/directoryApi/getPersonalCustomChildByParentId", payload);
}
export function getMetadataModelTree() {
return GetJSON("/metadatarepo/rest/model/tree");
}
......
......@@ -16,7 +16,7 @@ const AssetBrowse = (props) => {
const { reference = AssetBrowseReference } = props;
const [ nodeParams, setNodeParams ] = useState({ centerId: '', expandId: '' });
const [ nodeParams, setNodeParams ] = useState({ centerId: '', expandId: '', nodeType: '' });
const [ expandTree, setExpandTree ] = useState(true);
const [ expandRelation, setExpandRelation ] = useState(true);
const [ assetCount, setAssetCount ] = useState(0);
......@@ -25,7 +25,7 @@ const AssetBrowse = (props) => {
const { centerId, expandId } = nodeParams;
const onTreeSelect = (value, type) => {
setNodeParams({ centerId: value||'', expandId: '' });
setNodeParams({ centerId: value||'', expandId: '', nodeType: type });
}
const treeToggleClick = () => {
......@@ -79,7 +79,7 @@ const AssetBrowse = (props) => {
</React.Fragment>
}
<div style={{ flex: 1, overflow: 'hidden' }}>
<AssetTable nodeId={nodeId} reference={reference} onCountChange={onAssetCountChange} {...props} />
<AssetTable nodeId={nodeId} nodeType={nodeParams.nodeType} reference={reference} onCountChange={onAssetCountChange} {...props} />
</div>
</div>
</div>
......
......@@ -651,7 +651,7 @@ const AssetManageTree = (props) => {
);
if (item.children && item.children.length>0) {
return { ...item, ...{title, key: item.nodeId, children: loop(item.children, rootResourceType, false), className: (item.level===1)?'root':''} };
return { ...item, ...{title, key: item.nodeId, children: loop(item.children, rootResourceType), className: (item.level===1)?'root':''} };
}
if (rootResourceType !== 'custom') {
......
......@@ -386,8 +386,15 @@ const AssetTable = (props) => {
}
}
let url = 'assetmanage.listDataAssetsByPage';
if (reference===AssetRecycleReference) {
url = 'assetmanage.listRecycleBinDataAssetsByPage';
} else if ((reference===AssetBrowseReference|| reference===ResourceBrowseReference) && nodeType==='custom' ) {
url = 'assetmanage.listDataAssetsByPersonalCustomType';
}
dispatchLatestHomepage({
type: (reference===AssetRecycleReference)?'assetmanage.listRecycleBinDataAssetsByPage':'assetmanage.listDataAssetsByPage',
type: url,
payload: params,
callback: data => {
const _assets = [];
......
import React, { useEffect, useState, useRef } from 'react';
import {Card, Spin, Tooltip, Tree, Dropdown, Menu, Modal, AutoComplete} from 'antd';
import { PlusOutlined, ImportOutlined,ExportOutlined,ReloadOutlined, SettingOutlined } from '@ant-design/icons';
import classNames from 'classnames';
import {Card, Spin, Tooltip, Tree, Modal, AutoComplete} from 'antd';
import { ReloadOutlined, SettingOutlined } from '@ant-design/icons';
import { useContextMenu, Menu as RcMenu, Item as RcItem } from "react-contexify";
import { dispatch } from '../../../../model';
import ImportDirectory from './ImportDirectory';
import UpdateDirectoryModal from './UpdateDirectoryModal';
import CustomDirectoryModal from './CustomDirectoryModal';
import { showMessage, getQueryParam } from '../../../../util';
import { AnchorTimestamp, AnchorId, AssetManageReference, AssetBrowseReference, ResourceBrowseReference, AssetMountReference, AnchorDirId } from '../../../../util/constant';
import { AnchorTimestamp, AnchorId, AssetBrowseReference, ResourceBrowseReference, AnchorDirId } from '../../../../util/constant';
import { highlightSearchContentByTerms } from '../../../../util';
import './AssetTree.less';
......@@ -17,6 +14,23 @@ import 'react-contexify/dist/ReactContexify.css';
const { Option } = AutoComplete;
function updateTreeData(list, key, children) {
return list.map((node) => {
if (node.nodeId === key) {
return { ...node, children };
}
if (node.children) {
return {
...node,
children: updateTreeData(node.children, key, children),
};
}
return node;
});
}
const AssetTree = (props) => {
const MENU_ID = 'asset-tree';
......@@ -25,24 +39,19 @@ const AssetTree = (props) => {
id: MENU_ID,
});
const { checkable = false, onSelect, className, onCheck, tableId, reference=AssetManageReference, onDirectoryChange, centerId } = props;
const { onSelect, onCheck, tableId, reference=AssetBrowseReference, centerId } = props;
const [ keyword, setKeyword ] = useState('');
const [ loading, setLoading ] = useState(false);
const [ treeData, setTreeData ] = useState([]);
const [ dataList, setDataList ] = useState([]);
const [ groupIds, setGroupIds ] = useState([]);
const [ expandedKeys, setExpandedKeys ] = useState([]);
const [ checkedKeys, setCheckedKeys ] = useState([]);
const [ autoExpandParent, setAutoExpandParent ] = useState(false);
const [ currentDirId, setCurrentDirId ] = useState('');
const [ currentDirType, setCurrentDirType ] = useState('');
const [ currentRightClickDir, setCurrentRightClickDir ] = useState({});
const [ importDirectoryVisible, setImportDirectoryVisible ] = useState(false);
const [ updateDirectoryModalVisible, setUpdateDirectoryModalVisible ] = useState(false);
const [ updateDirectoryAction, setUpdateDirectoryAction ] = useState('');
const [ customDirectoryModalVisible, setCustomDirectoryModalVisible ] = useState(false);
const [ customDirectoryAction, setCustomDirectoryAction ] = useState('');
const [options, setOptions] = useState([]);
const [ loadedKeys, setLoadedKeys ] = useState([]);
const [modal, contextHolder] = Modal.useModal();
......@@ -122,7 +131,6 @@ const AssetTree = (props) => {
dataAssetId: tableId
},
callback: data => {
setCheckedKeys(data.dirIds||[]);
setExpandedKeys(data.dirIds||[]);
setAutoExpandParent(true);
onCheck && onCheck(data.dirIds||[]);
......@@ -138,9 +146,7 @@ const AssetTree = (props) => {
}
let url = '';
if (reference === AssetManageReference || reference === AssetMountReference) {
url = 'assetmanage.queryAllDirectoryAsTree';
} else if (reference === AssetBrowseReference) {
if (reference === AssetBrowseReference) {
url = 'assetmanage.queryAssetDirectoryAsTree';
} else if (reference === ResourceBrowseReference) {
url = 'assetmanage.queryResourceDirectoryAsTree';
......@@ -153,10 +159,7 @@ const AssetTree = (props) => {
let newData = [...data];
if (reference === AssetMountReference) {
newData = newData.filter(item => item.type!=='custom');
}
setLoadedKeys([]);
setTreeData(newData);
const _dataList = [], _groupIds = [];
......@@ -164,13 +167,19 @@ const AssetTree = (props) => {
generateGroupIds(newData, _groupIds);
setDataList(_dataList);
setGroupIds(_groupIds);
treeDataRef.current = newData;
dataListRef.current = _dataList;
let defaultItem = null;
if ((defaultSelectedId||'') === '') {
_dataList.forEach(item => {
if ((defaultSelectedId||'')==='') {
defaultSelectedId = item.key;
}
})
}
function recursion(subCatalogs) {
if ((subCatalogs||[]).length===0) return;
......@@ -205,18 +214,8 @@ const AssetTree = (props) => {
setAutoExpandParent(true);
setCurrentDirId(defaultItem.nodeId);
setCurrentDirType(defaultItem.type||'');
onSelect && onSelect(defaultItem.nodeId, defaultItem.type||'');
} else {
const _currentDirId = (newData&&newData[0]?(newData[0].nodeId||''):'');
const _type = (newData&&newData[0]?(newData[0].type||''):'');
setCurrentDirId(_currentDirId);
setCurrentDirType(_type);
onSelect && onSelect(_currentDirId, _type);
}
}
......@@ -263,7 +262,6 @@ const AssetTree = (props) => {
setAutoExpandParent(true);
setCurrentDirId(defaultItem.nodeId);
setCurrentDirType(defaultItem.type||'');
onSelect && onSelect(defaultItem.nodeId, defaultItem.type||'');
}
}
......@@ -271,6 +269,9 @@ const AssetTree = (props) => {
const generateList = (treeData, list, path = null) => {
for (let i = 0; i < treeData.length; i++) {
const node = treeData[i];
if (node.resourceType !== 'custom') {
const { nodeId, text } = node;
const currentPath = path ? `${path}/${text}` : text;
......@@ -279,6 +280,7 @@ const AssetTree = (props) => {
generateList(node.children, list, currentPath);
}
}
}
};
const generateGroupIds = (treeData, list) => {
......@@ -338,58 +340,10 @@ const AssetTree = (props) => {
return type;
}
const addDir = () => {
if (currentDirType==='custom') return;
setUpdateDirectoryAction('add');
setUpdateDirectoryModalVisible(true);
}
const editDir = () => {
if ((currentDirType||'') === '') {
setUpdateDirectoryAction('edit');
setUpdateDirectoryModalVisible(true);
} else if (currentDirType === 'custom') {
setCustomDirectoryAction('edit');
setCustomDirectoryModalVisible(true);
}
}
const refreshTree = () => {
getAllDirectoryAsTree(false);
}
const importDir = () => {
if (currentDirType==='custom') return;
setImportDirectoryVisible(true);
}
const exportAllDir = () => {
window.open('/api/dataassetmanager/directoryApi/export');
}
const exportCurrentDir = () => {
if(currentDirId){
dispatch({
type: 'assetmanage.getDirectoryById',
payload: {
dirId: currentDirId
},
callback: data => {
window.open(`/api/dataassetmanager/directoryApi/export?parentPath=${data.path}`);
}
})
} else {
showMessage("warn","请选择目录")
}
}
const deleteDir = () => {
if (currentRightClickDir.nodeId) {
modal.confirm({
......@@ -442,31 +396,6 @@ const AssetTree = (props) => {
setCustomDirectoryModalVisible(true);
}
// const onChange = (e) => {
// const { value } = e.target;
// if (value === '') {
// setExpandedKeys([]);
// setAutoExpandParent(false);
// setKeyword(value);
// return;
// }
// const expandedKeys = dataList
// .map(item => {
// if (item.title.indexOf(value) > -1) {
// return getParentKey(item.key, treeData);
// }
// return null;
// })
// .filter((item, i, self) => item && self.indexOf(item) === i);
// setExpandedKeys(expandedKeys);
// setAutoExpandParent(true);
// setKeyword(value);
// }
const onTreeSelect = (keys, _) => {
if ((keys||[]).length === 0) {
......@@ -477,59 +406,14 @@ const AssetTree = (props) => {
const _currentDirType = getCurrentType(keys[0], treeData);
setCurrentDirType(_currentDirType);
onSelect && onSelect(keys[0], _currentDirType);
}
const onTreeCheck = (values, e) => {
//同一主题下只能挂载一个目录
const _checkedKeysValue = [...(values.checked||[])];
if (e.checked) {
const _currentNodeId = e.node?.key;
let _groupItem = [];
groupIds.forEach(groupItem => {
groupItem.forEach(id => {
if (id === _currentNodeId) {
_groupItem = groupItem;
}
})
})
const _filterKeys = (_checkedKeysValue.filter(item => item===_currentNodeId || !(_groupItem.includes(item))));
setCheckedKeys(_filterKeys);
onCheck && onCheck(_filterKeys);
} else {
setCheckedKeys(_checkedKeysValue);
onCheck && onCheck(_checkedKeysValue);
}
}
const onExpand = (expandedKeys) => {
setExpandedKeys(expandedKeys);
setAutoExpandParent(false);
};
const onUpdateDirectoryCancel = (refresh=false, id) => {
setUpdateDirectoryModalVisible(false);
if (refresh) {
if (updateDirectoryAction === 'add') {
getAllDirectoryAsTree(true, id);
} else {
getAllDirectoryAsTree();
onDirectoryChange && onDirectoryChange();
}
}
}
const onImportDirectoryCancel = (refresh=false, resetCurrentDirId=false) => {
setImportDirectoryVisible(false);
refresh && getAllDirectoryAsTree(resetCurrentDirId);
}
const onCustomDirectoryCancel = (refresh=false, id='') => {
setCustomDirectoryModalVisible(false);
if (refresh) {
......@@ -563,50 +447,66 @@ const AssetTree = (props) => {
treeDirectoryChanged(option.key);
};
const exportMenu = (
<Menu>
<Menu.Item>
<div style={{ textAlign: 'center' }} onClick={() => exportAllDir()}>
导出所有
</div>
</Menu.Item>
<Menu.Item>
<div style={{ textAlign: 'center' }} onClick={() => exportCurrentDir()}>
导出选中目录
</div>
</Menu.Item>
</Menu>
);
const onLoadData = ({ key, children }) =>
new Promise((resolve) => {
if (children) {
resolve();
return;
}
setLoadedKeys([...loadedKeys, key]);
dispatch({
type: 'assetmanage.getPersonalCustomDirecotryChild',
payload: {
parentId: key,
},
callback: (data) => {
if (data && data.length>0) {
let newTreeData = updateTreeData(treeData, key, data);
setTreeData(newTreeData);
treeDataRef.current = newTreeData;
}
resolve();
},
error: () => {
resolve();
}
});
});
const loop = (data, isRootLeaf= true) =>
const loop = (data, rootResourceType = null) =>
data.map(item => {
if (item.level === 1) {
rootResourceType = item.type;
}
const title = (
<span
className={isRootLeaf?'title-color': 'text-color'}
className={(item.level===1)?'title-color': 'text-color'}
>
{item.text}
{
reference === AssetManageReference && <span>{` (${item.dataAssetAndSubDirCount})`}</span>
}
</span>
);
if (item.children) {
return { ...item, ...{title, key: item.nodeId, children: loop(item.children, false), isRootLeaf} };
if (item.children && item.children.length>0) {
return { ...item, ...{ title, key: item.nodeId, children: loop(item.children, rootResourceType) }};
}
return { ...item, ...{ title, key: item.nodeId, isRootLeaf }};
});
if (rootResourceType !== 'custom') {
return { ...item, ...{ title, key: item.nodeId, isLeaf: true }};
}
const classes = classNames('asset-tree', className, {
'asset-tree-read-only': (reference===AssetBrowseReference||reference===ResourceBrowseReference),
'asset-tree-asset-mount-reference': reference===AssetMountReference,
return { ...item, ...{ title, key: item.nodeId, children: null }};
});
return (
<Card
className={classes}
title={ (reference===AssetBrowseReference||reference===ResourceBrowseReference || reference===AssetMountReference) ? null : (
className='asset-tree asset-tree-read-only'
title={
<div
className='flex px-2'
style={{
......@@ -615,25 +515,15 @@ const AssetTree = (props) => {
justifyContent: 'space-around',
}}
>
<Tooltip title="新增目录">
<PlusOutlined className={(currentDirType==='custom')?'disable': 'default'} onClick={addDir} style={{ fontSize:16,cursor: (currentDirType==='custom')?'not-allowed':'pointer' }}/>
</Tooltip>
<Tooltip title="刷新目录">
<ReloadOutlined className='default' onClick={refreshTree} style={{ fontSize:16,cursor:'pointer' }} />
<ReloadOutlined className='default' onClick={refreshTree} style={{ fontSize:16,cursor:'pointer',flex:1}} />
</Tooltip>
<Tooltip title="导入目录">
<ImportOutlined className={(currentDirType==='custom')?'disable': 'default'} onClick={importDir} style={{ fontSize:16,cursor:(currentDirType==='custom')?'not-allowed':'pointer' }} />
</Tooltip>
<Dropdown overlay={exportMenu} placement="bottomCenter" >
<Tooltip title="导出目录">
<ExportOutlined className='default' style={{ fontSize:16,cursor:'pointer' }} />
</Tooltip>
</Dropdown>
<Tooltip title="自定义目录">
<SettingOutlined className='default' onClick={customDir} style={{ fontSize:16,cursor:'pointer' }} />
<SettingOutlined className='default' onClick={customDir} style={{ fontSize:16,cursor:'pointer',flex:1}} />
</Tooltip>
<div style={{ flex: 3 }}></div>
</div>
)}
}
bordered={false}
bodyStyle={{ padding: '10px 15px' }}
headStyle={{ padding: 0 }}
......@@ -661,60 +551,47 @@ const AssetTree = (props) => {
}
</AutoComplete>
<Tree
checkable={checkable}
showLine={true}
showIcon={false}
onExpand={onExpand}
expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent}
treeData={loop(treeData)}
loadData={onLoadData}
loadedKeys={loadedKeys}
selectedKeys={[currentDirId||'']}
onSelect={onTreeSelect}
onCheck={onTreeCheck}
checkedKeys={checkedKeys}
checkStrictly
onRightClick={({event, node}) => {
if (reference === AssetManageReference) {
if (node.level>1 && node.type==='custom') {
setCurrentRightClickDir(node);
setCurrentDirType(node.type||'');
displayMenu(event);
}
}}
/>
</Spin>
<UpdateDirectoryModal
visible={ updateDirectoryModalVisible }
onCancel={ onUpdateDirectoryCancel }
action={ updateDirectoryAction }
dirId={ (updateDirectoryAction==='add')?currentDirId:currentRightClickDir.nodeId }
/>
<ImportDirectory
visible={ importDirectoryVisible }
onCancel={ onImportDirectoryCancel }
dirId={ currentDirId }
/>
<CustomDirectoryModal
visible={ customDirectoryModalVisible }
onCancel={ onCustomDirectoryCancel }
action={ customDirectoryAction }
reference={ reference }
dirId= { currentDirId }
/>
{
(reference!==AssetMountReference) && <RcMenu id={MENU_ID}>
<RcMenu id={MENU_ID}>
{
currentRightClickDir && (currentRightClickDir.type!=='custom') && <RcItem id="edit" onClick={editDir}>
修改目录
</RcItem>
}
<RcItem id="up" onClick={() => { moveNode(1); }}>
currentRightClickDir && currentRightClickDir.level>1 && currentRightClickDir.type==='custom' && <RcItem id="up" onClick={() => { moveNode(1); }}>
上移目录
</RcItem>
<RcItem id="down" onClick={() => { moveNode(-1); }}>
}
{
currentRightClickDir && currentRightClickDir.level>1 && currentRightClickDir.type==='custom' && <RcItem id="up" onClick={() => { moveNode(-1); }}>
下移目录
</RcItem>
}
{
currentRightClickDir && (currentRightClickDir.type!=='custom'||(currentRightClickDir.type==='custom'&&currentRightClickDir.isRootLeaf)) && <RcItem id="delete" onClick={deleteDir}>
currentRightClickDir && currentRightClickDir.level===2 && currentRightClickDir.type==='custom' && <RcItem id="up" onClick={deleteDir}>
删除目录
</RcItem>
}
......
......@@ -7,11 +7,12 @@ import update from 'immutability-helper';
import DragTag from './DragTag';
import PreviewTree from './PreviewTree';
import { dispatch, dispatchLatest } from '../../../../model';
import { AssetManageReference, AssetBrowseReference, ResourceBrowseReference } from '../../../../util/constant';
import { showMessage } from '../../../../util';
const CustomDirectoryModal = (props) => {
const { visible, onCancel, action, dirId } = props;
const { visible, onCancel, action, dirId, reference = AssetManageReference } = props;
const [ keyword, setKeyword ] = useState('');
const [ data, setData ] = useState([]);
......@@ -67,11 +68,24 @@ const CustomDirectoryModal = (props) => {
}
const getPreviewTreeData = () => {
dispatchLatest({
type: 'assetmanage.previewTreeByCustomElements',
payload: {
let url = 'assetmanage.previewTreeByCustomElements';
let payload = {
data: checkedValues
},
}
if (reference===AssetBrowseReference || reference===ResourceBrowseReference) {
url = 'assetmanage.previewTreeByCustomElementsAndResourceType';
payload.params = {
resourceType: (reference===ResourceBrowseReference)?'resource':'dataAsset',
}
}
dispatchLatest({
type: url,
payload,
callback: data => {
setPreviewTreeData((data||[]).length>0?data[0]:{});
}
......@@ -127,8 +141,15 @@ const CustomDirectoryModal = (props) => {
payload.params = {...payload.params, dirId};
}
let url = 'assetmanage.saveTreeByCustomElements';
if (reference===AssetBrowseReference || reference===ResourceBrowseReference) {
url = 'assetmanage.saveTreeByCustomElementsAndResourceType';
payload.params = { ...payload.params, resourceType: (reference===ResourceBrowseReference)?'resource':'dataAsset' };
}
dispatch({
type: 'assetmanage.saveTreeByCustomElements',
type: url,
payload,
callback: data => {
setConfirmLoading(false);
......
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