Commit 3b52d2f5 by zhaochengxiang

资产管理

parent d13c8ab7
...@@ -109,6 +109,7 @@ const AddAssetModel = (props) => { ...@@ -109,6 +109,7 @@ const AddAssetModel = (props) => {
form={form} form={form}
dirId={nodeId} dirId={nodeId}
action='add' action='add'
reference={reference}
onMetadataChange={onMetadataChange} onMetadataChange={onMetadataChange}
onElementsChange={onElementsChange} onElementsChange={onElementsChange}
/> />
......
...@@ -101,7 +101,7 @@ const MetaModelSelect = ({ value = {}, metaModelTreeData = [], onChange, ...rest ...@@ -101,7 +101,7 @@ const MetaModelSelect = ({ value = {}, metaModelTreeData = [], onChange, ...rest
} }
const AttributeRelationModal = (props) => { const AttributeRelationModal = (props) => {
const { visible, onCancel, type = ResourceManageReference } = props; const { visible, onCancel, type = AssetManageReference } = props;
const [ confirmLoading, setConfirmLoading ] = useState(false); const [ confirmLoading, setConfirmLoading ] = useState(false);
const [ metadataModelTreeData, setMetadataModelTreeData ] = useState([]); const [ metadataModelTreeData, setMetadataModelTreeData ] = useState([]);
...@@ -201,7 +201,10 @@ const AttributeRelationModal = (props) => { ...@@ -201,7 +201,10 @@ const AttributeRelationModal = (props) => {
dispatch({ dispatch({
type: 'assetmanage.saveEleAndAttrRel', type: 'assetmanage.saveEleAndAttrRel',
payload: { payload: {
data: newRels data: newRels,
params: {
dataAssetType: getAssetType(type)
}
}, },
callback: data => { callback: data => {
reset(); reset();
......
import React from 'react'
import { Button, Modal, Spin, Tree, AutoComplete } from 'antd'
import { dispatch } from '../../../model'
import produce from 'immer'
import { highlightSearchContentByTerms, showMessage, showNotifaction } from '../../../util'
import { generateList } from '../AssetResourceManage/tree'
const FC = (props) => {
const { visible, items, onCancel } = props
const [waiting, setWaiting] = React.useState(false)
const basicRef = React.useRef()
const close = (refresh = false) => {
setWaiting(false)
onCancel?.(refresh)
}
const save = () => {
const checkedKeys = basicRef.current?.getCheckedKeys()
if ((checkedKeys??[]).length === 0) {
showMessage('warn', '请先选择资源目录')
return
}
setWaiting(true)
dispatch({
type: 'assetmanage.loadDataAssets',
payload: {
params: {
dirId: checkedKeys.join(","),
},
data: (items??[]).map(item => item.id)
},
callback: data => {
setWaiting(false)
if (data?.message) {
showNotifaction('提示', data?.message, 5)
}
onCancel?.(true)
},
error: () => {
setWaiting(false)
}
})
}
const footer = React.useMemo(() => {
return [
<Button key={'cancel'}
onClick={() => close()}
>取消</Button>,
<Button key={'save'} type='primary'
disabled={waiting}
onClick={() => save()}
>保存</Button>
]
}, [close, save, waiting])
return (
<Modal
visible={visible}
footer={footer}
width='400px'
bodyStyle={{ padding: '15px 15px 0px 15px', overflowX: 'auto', maxHeight: '80vh', height: 500 }}
title='变更目录'
centered destroyOnClose
onCancel={() => { close() }}
>
<Spin spinning={waiting}>
<Basic ref={basicRef} items={items} />
</Spin>
</Modal>
)
}
export default FC
export const Basic = React.forwardRef(function ({ items, onCheck }, ref) {
const [data, setData] = React.useState()
const [dataList, setDataList] = React.useState()
const [loading, setLoading] = React.useState(false)
const [checkedKeys, setCheckedKeys] = React.useState()
const [expandedKeys, setExpandedKeys] = React.useState([])
const [autoExpandParent, setAutoExpandParent] = React.useState(false)
const [options, setOptions] = React.useState()
const [keyword, setKeyword] = React.useState()
React.useImperativeHandle(ref, () => ({
getCheckedKeys: () => checkedKeys
}), [checkedKeys])
React.useEffect(() => {
getTreeData()
getAssetPaths()
}, [])
const treeData = React.useMemo(() => {
if (data) {
const newTreeData = produce(data, draft => {
const setNode = (g) => {
g.key = g.nodeId
g.title = g.text
g.children?.forEach((child) => {
setNode(child)
})
}
draft.forEach((child) => {
setNode(child)
})
})
return newTreeData
}
return []
}, [data])
const getAssetPaths = () => {
if ((items??[]).length > 0) {
dispatch({
type: 'assetmanage.getAssetPaths',
payload: {
dataAssetId: items[0].id,
},
callback: data => {
setCheckedKeys((data??[]).map(item => item.dirId))
}
})
}
}
const getTreeData = () => {
setLoading(true)
dispatch({
type: 'assetmanage.queryAllDirectoryAsTree',
callback: data => {
setLoading(false)
const newData = (data??[]).filter(item => item.resourceType !== 'custom')
setData(newData)
if ((newData??[]).length > 0) {
const newDataList = []
generateList(newData, newDataList)
setDataList(newDataList)
const firstNode = newData[0]
setExpandedKeys([firstNode.nodeId])
setAutoExpandParent(true)
}
},
error: () => {
setLoading(false)
}
})
}
const onTreeExpand = (expandedKeys) => {
setExpandedKeys(expandedKeys)
setAutoExpandParent(false)
}
const onTreeCheck = (values, e) => {
//同一主题下只能挂载一个目录
if (e.node?.level === 1) {
showMessage('warn', '栏目不允许勾选')
return
}
const newCheckedKeys = values.checked??[]
if (e.checked) {
const index = (dataList??[]).findIndex(item => item.nodeId === e.node?.key)
if (index !== -1) {
const currentSubjectNodeId = dataList[index].subjectNodeId
const filterChecktedKeys = newCheckedKeys.filter(key => {
if (key !== e.node?.key) {
const index = (dataList??[]).findIndex(item => item.nodeId === key)
if (index !== -1) {
return (dataList[index].subjectNodeId !== currentSubjectNodeId)
} else {
return false
}
}
return true
})
setCheckedKeys(filterChecktedKeys)
onCheck?.(filterChecktedKeys)
}
} else {
setCheckedKeys(newCheckedKeys)
onCheck?.(newCheckedKeys)
}
}
const onAutoCompleteSearch = (searchText) => {
setKeyword(searchText)
setOptions(!searchText?[]:(dataList||[]).filter(item => item.value.indexOf(searchText)!==-1))
}
const onAutoCompleteSelect = (value, option) => {
const paths = value.split('/')
setKeyword(paths[paths.length-1])
const newExpandedKeys = [...expandedKeys, option.key]
setExpandedKeys(Array.from(new Set(newExpandedKeys)))
setAutoExpandParent(true)
}
return (
<Spin spinning={loading}>
<AutoComplete
allowClear
value={keyword}
style={{ marginBottom: 10, width: '100%' }}
onSelect={onAutoCompleteSelect}
onSearch={onAutoCompleteSearch}
onClear={() => {
setKeyword()
}}
>
{
(options||[]).map((item, index) => {
return (
<AutoComplete.Option key={item.key} value={item.value}>
<div style={{ whiteSpace: 'normal' }}>
{highlightSearchContentByTerms(item.value, [keyword])}
</div>
</AutoComplete.Option>
);
})
}
</AutoComplete>
<Tree
checkable
checkStrictly
showLine
showIcon={false}
treeData={treeData}
autoExpandParent={autoExpandParent}
expandedKeys={expandedKeys}
checkedKeys={checkedKeys}
onExpand={onTreeExpand}
onCheck={onTreeCheck}
/>
</Spin>
)
})
\ No newline at end of file
import React, { useState } from 'react'; import React from "react"
import classNames from 'classnames'; import classNames from 'classnames'
import { Form } from 'antd'; import { ResizableBox } from 'react-resizable'
import { CaretLeftOutlined, CaretRightOutlined } from '@ant-design/icons'; import { Form } from "antd"
import { ResizableBox } from 'react-resizable'; import { CaretLeftOutlined, CaretRightOutlined } from '@ant-design/icons'
import AssetTree from './Component/AssetManageTree'; import Tree from './tree'
import AssetDirectory from './Component/AssetDirectory'; import Separate from './Component/Separate'
import AssetTable from './Component/AssetTable'; import NodeDetail from './Component/AssetDirectory'
import AssetAction from './Component/AssetAction'; import AssetList from './table'
import Separate from './Component/Separate'; import AssetDetail from './Component/AssetAction'
import { AssetManageReference } from "../../../util/constant"
import { AssetManageReference } from '../../../util/constant';
import './index.less'
import './index.less';
const FC = (props) => {
const AssetManage = (props) => { const [collapseTree, setCollapseTree] = React.useState(false)
const [node, setNode] = React.useState()
const [ nodeId, setNodeId ] = useState(''); const [asset, setAsset] = React.useState()
const [ nodeType, setNodeType ] = useState(''); const [assetListFullScreen, setAssetListFullScreen] = React.useState(false)
const [ nodeLevel, setNodeLevel ] = useState(null); const [directoryChanged, setDirectoryChanged] = React.useState(false)
const [ assetParams, setAssetParams ] = useState({ assetId: '', assetDirId: '' })
const [ expandTree, setExpandTree ] = useState(true); const [form] = Form.useForm()
const [ assetFullScreen, setAssetFullScreen ] = useState(false);
const onTreeClick = (value) => {
const [ assetCount, setAssetCount ] = useState(0); setDirectoryChanged(!directoryChanged)
const [ directoryChanged, setDirectoryChanged ] = useState(false); setNode(value)
const [ elementsChanged, setElementsChanged ] = useState(false);
const [ assetActionChanged, setAssetActionChanged ] = useState(false);
const [ form ] = Form.useForm();
const { assetId, assetDirId } = assetParams;
const onTreeSelect = (value, type, level) => {
setNodeId(value||'');
setNodeType(type);
setNodeLevel(level);
} }
const onTableSelect = (id, did) => { const onAssetListClick = (value) => {
setAssetParams({ assetId: id, assetDirId: did }); setAsset(value)
} }
const treeToggleClick = () => { const onAssetListFullScreenChange = (value) => {
setExpandTree(!expandTree); setAssetListFullScreen(value)
} }
const onElementsChange = () => { const treeToggleClick = () => {
setElementsChanged(!elementsChanged); setCollapseTree(!collapseTree)
}
const onDirectoryChange = () => {
setDirectoryChanged(!directoryChanged);
}
const onAssetActionChange = () => {
setAssetActionChanged(!assetActionChanged);
}
const onAssetCountChange = (count) => {
setAssetCount(count);
}
const onFullScreenChange = (value) => {
setAssetFullScreen(value);
} }
const classes = classNames('asset-manage', { const rootClasses = classNames('asset-manage', {
'asset-manage-collapse': !expandTree 'asset-manage-collapse': collapseTree
}); })
const middleClasses = classNames('middle', { const middleClasses = classNames('middle', {
'middle-fullscreen': assetFullScreen 'middle-fullscreen': assetListFullScreen
}); })
return ( return (
<div className={classes}> <div className={rootClasses}>
<ResizableBox <ResizableBox
className='left' className='left'
width={230} width={230}
height={Infinity} height={Infinity}
axis='x' axis='x'
minConstraints={[230, Infinity]} maxConstraints={[Infinity, Infinity]} minConstraints={[230, Infinity]}
maxConstraints={[Infinity, Infinity]}
> >
<AssetTree onSelect={onTreeSelect} onDirectoryChange={onDirectoryChange} {...props} /> <Tree onClick={onTreeClick} {...props} />
</ResizableBox> </ResizableBox>
{ {
expandTree && <Separate width={15} /> !collapseTree && <Separate width={15} />
} }
<div className={middleClasses}> <div className={middleClasses}>
<AssetDirectory id={nodeId} assetCount={assetCount} directoryChanged={directoryChanged} onElementsChange={onElementsChange} /> <NodeDetail
reference={AssetManageReference}
id={node?.nodeId}
assetCount={node?.dataAssetAndSubDirCount}
directoryChanged={directoryChanged}
/>
<Separate height={15} /> <Separate height={15} />
<AssetTable nodeId={nodeId} nodeType={nodeType} nodeLevel={nodeLevel} reference={AssetManageReference} elementsChanged={elementsChanged} assetActionChanged={assetActionChanged} onSelect={onTableSelect} onCountChange={onAssetCountChange} onFullScreenChange={onFullScreenChange} {...props} /> <AssetList
node={node}
onClick={onAssetListClick}
onFullScreenChange={onAssetListFullScreenChange}
{...props}
/>
<div className='tree-toggle' onClick={treeToggleClick}> <div className='tree-toggle' onClick={treeToggleClick}>
{ expandTree ? <CaretLeftOutlined /> : <CaretRightOutlined /> } { !collapseTree ? <CaretLeftOutlined /> : <CaretRightOutlined /> }
</div> </div>
</div> </div>
<Separate width='15px' /> <Separate width='15px' />
<div className='right'> <div className='right'>
<AssetAction form={form} id={assetId} dirId={assetDirId} action='detail' reference={AssetManageReference} onChange={onAssetActionChange} /> <AssetDetail
form={form}
id={asset?.id}
dirId={asset?.dirId}
action='detail'
reference={AssetManageReference}
/>
</div> </div>
</div> </div>
) )
} }
export default AssetManage; export default FC
\ No newline at end of file \ No newline at end of file
import React from 'react'
import classNames from 'classnames'
import { Tooltip, Typography, Space, Dropdown, Button, Menu, Checkbox, Input, Select, Modal, Table as AntdTable } from 'antd'
import ResizeObserver from 'rc-resize-observer'
import { debounceTime, Subject } from 'rxjs'
import { DownOutlined, UpOutlined } from "@ant-design/icons"
import LocalStorage from 'local-storage'
import { defaultPage, usePage } from '../../../util/hooks/page'
import Table from '../../../util/Component/Table'
import { dispatch } from '../../../model'
import { getAssetRange, getAssetType, getQueryParam, IsArr, isSzseEnv, showMessage, showNotifaction } from '../../../util'
import { AssetManageReference } from '../../../util/constant'
import PermissionButton from '../../../util/Component/PermissionButton'
import PermissionMenuItem from '../../../util/Component/PermissionMenuItem'
import { FullScreenSvg, CancelFullScreenSvg } from './Component/AssetSvg'
import ImportAsset from './Component/ImportAssetDrawer'
import ChangeCatalog from './change-catalog'
import AssetDelete from './Component/AssetDeleteModal'
import FilterElement from './Component/FilterElementModal'
import FilterElementValue from '../AssetResourceManage/filter-element-value'
import SelectBatchEditElements from '../AssetResourceManage/select-batch-edit-elements'
import { AssetDirectorySubject } from './Component/AssetDirectory'
import { AssetActionSubject } from './Component/AssetAction'
import TagCell from '../Model/Component/tag-help'
import './Component/AssetTable.less'
import { MetadataColumn } from '../AssetResourceManage/table'
const operationMap = {
}
const FC = (props) => {
const { node, onClick, onFullScreenChange } = props
const [args, setArgs] = React.useState(() => ({
params: {
page: defaultPage.pageNum,
size: defaultPage.pageSize,
catalogType: 'currentRecursive',
keyword: undefined,
resourceStatus: undefined,
elementValueFilters: []
},
}))
const [fullScreen, setFullScreen] = React.useState(false)
const [compact, setCompact] = React.useState(false)
const [loading, setLoading] = React.useState(false)
const [loadingElements, setLoadingElements] = React.useState(false)
const [columns, setColumns] = React.useState()
const [elements, setElements] = React.useState()
const [data, setData] = React.useState()
const [total, setTotal] = React.useState()
const [selectedRows, setSelectedRows] = React.useState([])
const [row, setRow] = React.useState()
const [rightRow, setRightRow] = React.useState()
const [permissions, setPermissions] = React.useState([])
const [loadingRelatedMetadataStatus, setLoadingRelatedMetadataStatus] = React.useState(false)
const [relatedMetadataStatus, setRelatedMetadataStatus] = React.useState()
const $keyword = React.useMemo(() => new Subject(), [])
const [keyword, setKeyword] = React.useState()
const [searchType, setSearchType] = React.useState('keyword')
const [resoureTagMap, setResourceTagMap] = React.useState()
const [addAssetParams, setAddAssetParams] = React.useState({
visible: false,
reference: undefined,
nodeId: undefined
})
const [importAssetParams, setImportAssetParams] = React.useState({
visible: false,
reference: undefined,
nodeId: undefined
})
const [changeCatalogParams, setChangeCatalogParams] = React.useState({
visible: false,
items: undefined
})
const [assetDeleteParams, setAssetDeleteParams] = React.useState({
visible: false
})
const [filterElementParams, setFilterElementParams] = React.useState({
visible: false,
type: undefined,
reference: undefined
})
const [filterElementValueParams, setFilterElementValueParams] = React.useState({
visible: false,
type: undefined,
defaultValue: undefined,
})
const [selectBatchEditElementsParams, setSelectBatchEditElementsParams] = React.useState({
visible: false,
type: undefined
})
const [page, setPage] = usePage()
const [modal, contextHolder] = Modal.useModal()
const locationIdRef = React.useRef(getQueryParam('id', props?.location?.search))
const locationDidRef = React.useRef(getQueryParam('did', props?.location?.search))
const setArgsAndPage = React.useCallback((params) => {
// 设置查询参数时将分页置为1
setPage(prevpg => {
setArgs((prev) => {
const newparams = params ? { ...prev.params, ...params } : undefined
return { params: { ...newparams, page: 1, size: prevpg.pageSize } }
})
return ({ ...prevpg, pageNum: 1 })
})
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
const setPageAndArgs = React.useCallback((page) => {
setPage(prev => ({ ...prev, ...page }))
setArgs((prev) => {
return { params: { ...prev.params, page: page.pageNum, size: page.pageSize } }
})
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
const storageChange = (e) => {
if (e.key === 'editAssetsChange') {
getAssets()
} else if (e.key === 'assetRelationOnClickEvent') {
locationIdRef.current = e.relation?.dataAssetId
locationDidRef.current = e.relation?.dirId
} else if (e.key === 'assetPathOnClickEvent') {
locationIdRef.current = e.id
locationDidRef.current = e.dirId
}
}
React.useEffect(() => {
getElements()
getResourceRelatedMetadataStatus()
const $$keyword = $keyword.pipe(debounceTime(1000)).subscribe((keyword) => {
setArgsAndPage({ keyword })
})
const $$assetDirectorySubject = AssetDirectorySubject.subscribe((props) => {
if (props.type === 'element-change') {
getElements()
}
})
const $$assetActionSubject = AssetActionSubject.subscribe((props) => {
if (props.type === 'asset-change') {
getAssets()
}
})
window?.addEventListener("storage", storageChange)
return () => {
$$keyword.unsubscribe()
$$assetDirectorySubject.unsubscribe()
$$assetActionSubject.unsubscribe()
window?.removeEventListener("storage", storageChange)
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
React.useEffect(() => {
if (node) {
getPermissions()
setRow()
setSelectedRows([])
if (locationIdRef.current && locationDidRef.current) {
getDataAssetLocation()
} else {
setPageAndArgs({ pageNum: 1, pageSize: page.pageSize })
}
}
}, [node])
React.useEffect(() => {
if (node?.nodeId) {
getAssets()
}
}, [args])
React.useEffect(() => {
if (data) {
getResourceTag()
}
}, [data])
const [addAble, batchEditAble, importAble, exportAble, changeDirectoryAble, deleteAble] = React.useMemo(() => {
let [_addAble, _batchEditAble, _importAble, _exportAble, _changeDiretoryAble, _deleteAble] = [false, false, false, false, false, false]
_addAble = (permissions??[]).findIndex(item => item==='add') !== -1
if ((selectedRows??[]).length === 0) {
_importAble = (permissions??[]).findIndex(item => item==='import') !== -1
_exportAble = (permissions??[]).findIndex(item => item==='export') !== -1
} else {
let [allowImport, allowExport] = [true, true]
for (const row of selectedRows) {
const importIndex = (row.allowButtons??[]).findIndex(item => item==='import')
const exportIndex = (row.allowButtons??[]).findIndex(item => item==='export')
if (importIndex === -1) {
allowImport = false
}
if (exportIndex === -1) {
allowExport = false
}
}
_importAble = allowImport
_exportAble = allowExport
}
let [allowBatchEdit, allowChangeDirectory, allowDelete] = [true, true, true]
for (const row of selectedRows) {
const batchEditIndex = (row.allowButtons??[]).findIndex(item => item==='batchEdit')
const changeDirecotoryIndex = (row.allowButtons??[]).findIndex(item => item==='changeDir')
const deleteIndex = (row.allowButtons??[]).findIndex(item => item==='delete')
if (batchEditIndex === -1) {
allowBatchEdit = false
}
if (changeDirecotoryIndex === -1) {
allowChangeDirectory = false
}
if (deleteIndex === -1) {
allowDelete = false
}
}
_batchEditAble = allowBatchEdit
_changeDiretoryAble = allowChangeDirectory
_deleteAble = allowDelete
return [_addAble, _batchEditAble, _importAble, _exportAble, _changeDiretoryAble, _deleteAble]
}, [permissions, selectedRows])
const menuData = React.useMemo(() => {
const newMenuData = []
for (const key of rightRow?.allowButtons??[]) {
if (operationMap[`${key}`]) {
newMenuData.push(operationMap[`${key}`])
}
}
return newMenuData
}, [rightRow])
const notElementCol = [
// {
// title: '梳理状态',
// dataIndex: 'sortingStatus',
// ellipsis: true,
// width: 120,
// render: (_, record) => record.resourceExtraAttribute?.sortingStatus
// },
// {
// title: '当前处理人',
// dataIndex: 'currentProcessor',
// ellipsis: true,
// width: 120,
// render: (_, record) => record.resourceExtraAttribute?.currentProcessor
// },
// {
// title: '任务编号',
// dataIndex: 'taskNO',
// ellipsis: true,
// width: 120,
// render: (_, record) => <a onClick={() => {
// window.open(`/center-home/menu/task-manage?id=${record.resourceExtraAttribute?.taskNO}`)
// }}>
// {record.resourceExtraAttribute?.taskNO}
// </a>
// },
// {
// title: '资产状态',
// dataIndex: 'resourceStatus',
// ellipsis: true,
// width: 120,
// render: (_, record) => record.resourceExtraAttribute?.resourceStatus
// },
// {
// title: '是否资产',
// dataIndex: 'transferDataAsset',
// ellipsis: true,
// width: 120,
// render: (_, record) => record.resourceExtraAttribute?.transferDataAsset
// },
{
title: '标签',
dataIndex: 'tag',
width: 360,
className: 'table-tag-cell',
render: (_, record) => <TagCell
id={record.id}
did={record.dirId}
type='dataAsset'
tags={resoureTagMap?.[`${record.id}`]}
/>
}
]
React.useEffect(() => {
const newColumns = []
let index = 0
for (const element of elements??[]) {
const col = {
title: element.name,
dataIndex: `element${++index}`,
ellipsis: true,
width: 120,
render: (text, record) => {
return (
<Tooltip title={text}>
<Typography.Text ellipsis={true}>
{text}
</Typography.Text>
</Tooltip>
);
}
}
if (element.name === '编号') {
col.width = 60
} else if (element.name === '中文名称') {
col.width = isSzseEnv ? 230 : 160
} else if (element.name === '英文名称') {
col.width = isSzseEnv ? 224 : 160
} else if (element.name === '资产路径') {
col.render = (text, record) => {
return (
<Tooltip title={text}>
<Typography.Text ellipsis={true}>
<a onClick={()=>{
let event = new Event('storage')
event.key = 'assetDirChangeEvent'
event.dirId = record.dirId
window?.dispatchEvent(event)
}}>
{text}
</a>
</Typography.Text>
</Tooltip>
)
}
} else if (element.metadataItem === '是') {
col.width = isSzseEnv ? 250 : 120
col.render = (text, record) => <MetadataColumn data={text} />
}
newColumns.push(col)
}
setColumns([...newColumns, ...notElementCol])
}, [elements, resoureTagMap])
const tableData = React.useMemo(() => {
const newTableData = []
for (const item of (data??[])) {
const newAsset = {...item}
let index = 0
for (const elementValue of (item.elementValues??[])) {
newAsset[`element${++index}`] = elementValue
}
newTableData.push(newAsset)
}
return newTableData
}, [data])
const tableMaxHeight = React.useMemo(() => {
return fullScreen ? 'calc(100vh - 209px - 72px)' : 'calc(100vh - 209px - 123px - 15px - 72px)'
}, [fullScreen])
const getPermissions = () => {
dispatch({
type: 'assetmanage.getPrivilegeByRangeAndDirId',
payload: {
range: getAssetRange(AssetManageReference),
optionId: node?.nodeId
},
callback: data => {
setPermissions(data)
}
})
}
const getResourceRelatedMetadataStatus = () => {
setLoadingRelatedMetadataStatus(true)
dispatch({
type: 'assetmanage.getResourceRelatedMetadataStatus',
callback: data => {
setLoadingRelatedMetadataStatus(false)
setRelatedMetadataStatus(data)
},
error: () => {
setLoadingRelatedMetadataStatus(false)
}
})
}
const getElements = () => {
setLoadingElements(true)
dispatch({
type: 'assetmanage.listFilterElements',
payload: {
range: getAssetRange(AssetManageReference),
dataAssetType: getAssetType(AssetManageReference)
},
callback: data => {
setLoadingElements(false)
setElements(data)
},
error: () => {
setLoadingElements(false)
}
})
}
const getAssets = () => {
setLoading(true)
let [recursive, dirId] = [true, node?.nodeId]
if (args.params.catalogType === 'current') {
recursive = false
}
if (args.params.catalogType === 'fullSearch') {
dirId = ''
}
dispatch({
type: 'assetmanage.listDataResourcesByPage',
payload: {
data: args.params.elementValueFilters??[],
params: {
dirId,
pageNum: args.params.page,
pageSize: args.params.size,
keyword: args.params.keyword,
range: getAssetRange(AssetManageReference),
resourceStatus: args.params.resourceStatus,
sortingStatus: args.params.sortingStatus,
recursive,
filterTodo: args.params.onlyPending,
}
},
callback: data => {
setLoading(false)
setData(data?.data)
setTotal(data?.total)
if (locationIdRef.current) {
const index = (data?.data??[]).findIndex(item => item.id === locationIdRef.current)
if (index !== -1) {
onClick?.(data?.data[index])
setRow(data?.data[index])
} else {
if ((data?.data??[]).length > 0) {
onClick?.(data?.data[0])
setRow(data?.data[0])
} else {
onClick?.(undefined)
setRow()
}
}
setTimeout(() => {
var anchor = document.getElementById(`${locationIdRef.current}`)
anchor?.scrollIntoView()
locationIdRef.current = null
locationDidRef.current = null
}, 500)
} else {
setRow(prevRow => {
if (!prevRow || (data?.data??[]).findIndex(item => item.id === prevRow.id) === -1) {
if ((data?.data??[]).length > 0) {
onClick?.(data?.data[0])
return data?.data[0]
} else {
onClick?.(undefined)
return undefined
}
}
return prevRow
})
}
},
error: () => {
setLoading(false)
locationIdRef.current = null
locationDidRef.current = null
}
})
}
const getResourceTag = () => {
const ids = (data??[]).map(item => item.id)
if (ids.length > 0) {
dispatch({
type: 'tag.getResourceTagIn',
payload: {
params: {
resourceIds: ids,
includeAll: true,
includePrivate: true
}
},
callback: data => {
setResourceTagMap(data?.data)
}
});
} else {
setResourceTagMap()
}
}
const getDataAssetLocation = () => {
setLoading(true)
dispatch({
type: 'assetmanage.getDataAssetLocation',
payload: {
dataAssetId: locationIdRef.current,
dirId: locationDidRef.current,
},
callback: data => {
const newPageNum = parseInt(data.offset/page.pageSize + ((data.offset%page.pageSize===0)?0:1))
setPageAndArgs({ ...page, pageNum: newPageNum })
},
error: () => {
setLoading(false)
locationIdRef.current = null
locationDidRef.current = null
setPageAndArgs({ ...page, pageNum: 1 })
}
})
}
const onAddClick = () => {
setAddAssetParams({
visible: true,
reference: AssetManageReference,
nodeId: node?.nodeId
})
}
const onBatchEditClick = () => {
setSelectBatchEditElementsParams({
visible: true,
type: AssetManageReference
})
}
const onImportClick = () => {
setImportAssetParams({
visible: true,
reference: AssetManageReference,
nodeId: node?.nodeId
})
}
const onExportClick = () => {
if ((selectedRows??[]).length === 0) {
modal.confirm({
title: '提示',
content: '是否导出选中目录下的所有资产?',
onOk: () => {
window.open(`/api/dataassetmanager/dataAssetApi/exportByDataAssetIds?dirId=${node?.nodeId}&recursive=${args.params.catalogType === 'currentRecursive'}&dataAsset=${getAssetRange(AssetManageReference)}`);
}
})
} else {
window.open(`/api/dataassetmanager/dataAssetApi/exportByDataAssetIds?dataAssetIds=${selectedRows.map(item => item.id).join(',')}&dataAsset=${getAssetRange(AssetManageReference)}`);
}
}
const onChangeDirectoryClick = () => {
setChangeCatalogParams({
visible: true,
items: selectedRows
})
}
const onDeleteClick = () => {
setAssetDeleteParams({
visible: true
})
}
const onFilterElementClick = () => {
setFilterElementParams({
visible: true,
type: 'admin',
reference: AssetManageReference
})
}
const deleteAssets = () => {
setAssetDeleteParams({
visible: false
})
dispatch({
type: 'assetmanage.unloadDataAssets',
payload: {
data: (selectedRows??[]).map(item => {
return { dataAssetId: item.id, dirId: item.dirId }
})
},
callback: () => {
showMessage("success","删除成功")
getAssets()
setSelectedRows([])
}
})
}
const deleteAssetsFromAllDirs = () => {
setAssetDeleteParams({
visible: false
})
dispatch({
type: 'assetmanage.unloadDataAssetsFromAllDirs',
payload: {
data: (selectedRows??[]).map(item => item.id)
},
callback: () => {
showMessage("success","删除成功")
getAssets()
setSelectedRows([])
}
})
}
const onMenuClick = ({ key }) => {
if (key === 'batchEdit') {
onBatchEditClick()
} else if (key === 'import') {
onImportClick()
} else if (key === 'export') {
onExportClick()
} else if (key === 'changeDir') {
onChangeDirectoryClick()
} else if (key === 'delete') {
onDeleteClick()
} else if (key === 'colConfig') {
onFilterElementClick()
}
}
const onRightMenuItemClick = (key, record) => {
}
const moreMenu = (
<Menu onClick={onMenuClick}>
{
compact && <React.Fragment>
<PermissionMenuItem
key='batchEdit'
defaultPermission={batchEditAble}
disabled={(selectedRows??[]).length===0}
tip={(selectedRows??[]).length===0?'请先选择资产':''}
>
<div className='text-center'>
批量编辑
</div>
</PermissionMenuItem>
</React.Fragment>
}
{
(node?.resourceType !== 'custom' && node?.type !== 'custom') && <PermissionMenuItem key='import' defaultPermission={importAble}>
<div className='text-center'>
导入
</div>
</PermissionMenuItem>
}
<PermissionMenuItem key='export' defaultPermission={exportAble}>
<div className='text-center'>
导出
</div>
</PermissionMenuItem>
<PermissionMenuItem
key='changeDir'
defaultPermission={changeDirectoryAble}
disabled={(selectedRows??[]).length===0}
tip={(selectedRows??[]).length===0?'请先选择资产':''}
>
<div className='text-center'>
变更目录
</div>
</PermissionMenuItem>
{
(node?.resourceType !== 'custom' && node?.type !== 'custom') && <PermissionMenuItem
key='delete'
defaultPermission={deleteAble}
disabled={(selectedRows??[]).length===0}
tip={(selectedRows??[]).length===0?'请先选择资产':''}
>
<div className='text-center'>
删除
</div>
</PermissionMenuItem>
}
<Menu.Item key='colConfig'>
<div className='text-center'>
可见列设置
</div>
</Menu.Item>
</Menu>
)
const classes = classNames('asset-list', {
'asset-list-fullscreen': fullScreen,
});
return (
<div className={classes}>
<div
className='flex'
style={{
padding: '20px 15px 5px',
alignItems: 'center',
justifyContent: 'space-between',
}}
>
<Space className='mr-3' style={{ flex: 0, paddingBottom: 15 }}>
{
(node?.level !== 1 && node?.resourceType !== 'custom' && node?.type !== 'custom') && <PermissionButton
defaultPermission={addAble}
onClick={onAddClick}
>
新增
</PermissionButton>
}
{
compact ? <Dropdown overlay={moreMenu} placement="bottomCenter">
<Button>更多</Button>
</Dropdown> : <React.Fragment>
<PermissionButton
defaultPermission={batchEditAble}
onClick={onBatchEditClick}
disabled={(selectedRows??[]).length===0}
tip={(selectedRows??[]).length===0?'请先选择资产':''}
>
批量编辑
</PermissionButton>
<Dropdown overlay={moreMenu} placement="bottomCenter">
<Button>更多</Button>
</Dropdown>
</React.Fragment>
}
</Space>
<div className='flex' style={{ flex: 1, overflow: 'auto', paddingBottom: 15 }}>
<div style={{ flex: 1 }}></div>
<Space style={{ flex: 0 }}>
<Select
value={args.params.catalogType}
onChange={(value) => {
setArgsAndPage({ catalogType: value })
}}
style={{ width: 170 }}
>
<Select.Option value='currentRecursive'>
当前目录(含子目录)
</Select.Option>
<Select.Option value='current'>
当前目录
</Select.Option>
<Select.Option value='fullSearch'>
全部数据
</Select.Option>
</Select>
<Select
placeholder='资产状态'
onChange={(value) => {
setArgsAndPage({ resourceStatus: value })
}}
style={{ width: 100 }}
allowClear
>
{
(relatedMetadataStatus??[]).map((item, index) => {
return <Select.Option key={index} value={item.type}>
{item.desc}
</Select.Option>
})
}
</Select>
<Input size="middle"
addonBefore={
<Select
value={searchType}
onChange={(value) => {
setSearchType(value)
if (value === 'attribute') {
setFilterElementValueParams({
visible: true,
type: AssetManageReference,
defaultValue: args.params.elementValueFilters
})
}
}}
style={{ width: 120 }}
>
<Select.Option value='keyword'>
关键字搜索
</Select.Option>
<Select.Option value='attribute'>
属性值过滤
</Select.Option>
</Select>
}
placeholder="资产要素值/任务"
value={keyword}
bordered={true} allowClear
onChange={(e) => {
const keyword = e.target.value
setKeyword(keyword)
$keyword.next((keyword??'').trim())
}}
style={{ width: 270 }}
/>
<Tooltip title={fullScreen?'取消全屏':'全屏'}>
<Button
onClick={() => {
setFullScreen(!fullScreen)
onFullScreenChange?.(!fullScreen)
}}
icon={fullScreen ?<CancelFullScreenSvg style={{ width: 20, height: 20, marginTop: 2 }} /> : <FullScreenSvg style={{ width: 20, height: 20, marginTop: 2 }} />}
type='text'
/>
</Tooltip>
</Space>
</div>
</div>
<div className='px-3'>
<ResizeObserver
onResize={({ width }) => {
setCompact(width < 1030)
}}
>
<Table
maxHeight={tableMaxHeight}
loading={loading||loadingElements}
columns={columns}
dataSource={tableData}
pageSize={page.pageSize} pageNum={page.pageNum} total={total??0}
onRowClick={(event, value) => {
setRow(value)
onClick?.(value)
}}
rowClassName={(record, index) => (record?.id === row?.id) ? 'yy-table-select-row' : ''}
onPaginate={(page, pageSize) => {
setRow()
setSelectedRows([])
setPageAndArgs({ pageNum: page, pageSize })
}}
rowSelection={{
selectedRowKeys: (selectedRows??[]).map(item => item.id),
onChange: (selectedRowKeys, selectedRows) => {
setSelectedRows(selectedRows)
},
}}
shouldRowContextMenu={(record) => {
setRightRow(record)
let allowContextMenu = false
for (const key of (record.allowButtons??[])) {
if (operationMap[`${key}`]) {
allowContextMenu = true
}
}
return allowContextMenu
}}
menuData={menuData}
menuPermissions={menuData}
onMenuItemClick={onRightMenuItemClick}
/>
</ResizeObserver>
</div>
<ImportAsset
{...importAssetParams}
onCancel={() => {
setImportAssetParams({
visible: false,
reference: undefined,
nodeId: undefined
})
}}
onSuccess={(tip = '') => {
getAssets()
if (tip) {
showNotifaction('导入提示', tip, 5)
}
}}
/>
<AssetDelete
{...assetDeleteParams}
onCancel={() => {
setAssetDeleteParams({
visible: false
})
}}
onDelete={deleteAssets}
onDeleteAll={deleteAssetsFromAllDirs}
/>
<FilterElement
{...filterElementParams}
onCancel={(refresh = false) => {
setFilterElementParams({
visible: false,
type: undefined,
reference: undefined
})
refresh && getElements()
}}
/>
<FilterElementValue
{...filterElementValueParams}
onCancel={(refresh, val) => {
setFilterElementValueParams({
visible: false,
type: undefined,
defaultValue: undefined,
})
setSearchType('keyword')
if (refresh) {
setArgsAndPage({ elementValueFilters: val })
}
}}
/>
<SelectBatchEditElements
{...selectBatchEditElementsParams}
onCancel={(refresh, value) => {
setSelectBatchEditElementsParams({
visible: false,
type: undefined,
})
if (refresh) {
setTimeout(() => {
window.open(`/data-govern/edit-assets?ids=${(selectedRows??[]).map(item => item.id).toString()}&elementIds=${(value??[]).toString()}`)
}, 300)
}
}}
/>
<ChangeCatalog
{...changeCatalogParams}
onCancel={(refresh = false) => {
setChangeCatalogParams({
visible: false,
items: undefined
})
refresh && getAssets()
}}
/>
{contextHolder}
</div>
)
}
export default FC
\ No newline at end of file
import React, { useEffect, useMemo, useState } from 'react';
import { Tooltip, Spin, Modal, Button, AutoComplete, Menu, Dropdown } from 'antd'
import { PlusOutlined, ReloadOutlined, ImportOutlined, ExportOutlined, SettingOutlined } from '@ant-design/icons'
import produce from 'immer'
import { dispatch } from '../../../model'
import { showMessage, highlightSearchContentByTerms, showNotifaction, getAssetType, getAssetRange } from '../../../util'
import Tree from '../../../util/Component/Tree'
import PermissionButton from '../../../util/Component/PermissionButton'
import ImportNode from './Component/ImportDirectory'
import CustomNode from './Component/CustomDirectoryModal'
import { AssetManageReference } from '../../../util/constant'
import { generateList, updateTreeData } from '../AssetResourceManage/tree'
import UpdateNode from './Component/UpdateDirectoryModal'
import '../AssetResourceManage/tree.less'
const FC = (props) => {
const {onClick} = props
const [loading, setLoading] = useState(false)
const [data, setData] = useState(undefined)
const [dataList, setDataList] = useState()
const [keyword, setKeyword] = useState()
const [options, setOptions] = useState()
const [expandedKeys, setExpandedKeys] = useState([])
const [loadedKeys, setLoadedKeys] = useState([])
const [selectedKey, setSelectedKey] = useState('')
const [rightSelectedNode, setRightSelectedNode] = useState()
const [autoExpandParent, setAutoExpandParent] = useState(false)
const [updateNodeParam, setUpdateNodeParam] = useState({
visible: false,
action: undefined,
id: undefined,
})
const [importNodeParam, setImportNodeParam] = useState({
visible: false,
reference: undefined,
dirId: undefined
})
const [customNodeParam, setCustomNodeParam] = useState({
visible: false,
reference: undefined
})
const [permissions, setPermissions] = useState()
const [modal, contextHolder] = Modal.useModal()
const storageChange = (e) => {
if (e.key === 'assetDirChangeEvent' || e.key === 'assetPathOnClickEvent') {
if (e.dirId) {
setSelectedKey(e.dirId)
resetSelectedNodeLogic()
}
} else if (e.key === 'assetRelationOnClickEvent') {
setSelectedKey(e.relation?.dirId)
resetSelectedNodeLogic()
}
}
useEffect(() => {
getTreeData()
getPermissions()
window?.addEventListener("storage", storageChange)
return () => {
window?.removeEventListener("storage", storageChange)
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
const havePermission = useMemo(() => {
return (permissions??[]).findIndex(item => item === 'dirManage') !== -1
}, [permissions])
const treeData = useMemo(() => {
if (data) {
const newTreeData = produce(data, draft => {
const setNode = (g) => {
g.key = g.nodeId
g.title = (
<span className={(g.level===1)?'title-color':'text-color'}>
{g.text}
{
//自定义类型栏目不统计资产数
(g.level === 1 && g.resourceType === 'custom') ? null : <span>{` (${g.dataAssetAndSubDirCount})`}</span>
}
</span>
)
g.children?.forEach((child) => {
setNode(child)
})
if (g.resourceType !== 'custom' && g.type !== 'custom' && (g.children??[]).length === 0) {
g.isLeaf = true
}
if ((g.resourceType === 'custom'||g.type === 'custom') && (g.children??[]).length === 0) {
g.children = null
}
}
draft.forEach((child) => {
setNode(child)
})
})
return newTreeData
}
return []
}, [data])
const menuData = useMemo(() => {
if (rightSelectedNode) {
if (rightSelectedNode.level === 1) {
return [
{ id: 'edit', title: '编辑栏目' },
{ id: 'up', title: '上移栏目' },
{ id: 'down', title: '下移栏目' },
{ id: 'delete', title: '删除栏目' },
]
} else if (rightSelectedNode.resourceType === 'custom' || rightSelectedNode.type === 'custom') {
return [
{ id: 'up', title: '上移目录' },
{ id: 'down', title: '下移目录' },
{ id: 'delete', title: '删除目录' },
]
} else {
return [
{ id: 'edit', title: '编辑目录' },
{ id: 'up', title: '上移目录' },
{ id: 'down', title: '下移目录' },
{ id: 'delete', title: '删除目录' },
]
}
}
return []
}, [rightSelectedNode])
const resetSelectedNodeLogic = () => {
setData(prevData => {
setSelectedKey(prevSelectedKey => {
if ((prevData??[]).length === 0) return;
const firstNode = prevData[0]
if (!prevSelectedKey) {
setExpandedKeys(Array.from(new Set([...expandedKeys, firstNode.nodeId])))
setAutoExpandParent(true)
onTreeSelect([firstNode.nodeId], { selectedNodes: [firstNode]})
} else {
setDataList(prevDataList => {
const filterNodes = (prevDataList??[]).filter(item => item.nodeId === prevSelectedKey)
if (filterNodes?.length > 0) {
const newExpandedKeys = [...expandedKeys, prevSelectedKey]
setExpandedKeys(Array.from(new Set(newExpandedKeys)))
setAutoExpandParent(true)
onTreeSelect([prevSelectedKey], {selectedNodes: filterNodes})
}
return prevDataList
})
}
return prevSelectedKey
})
return prevData
})
}
const getTreeData = (resetSelectedNode = true) => {
setLoading(true)
setSelectedKey(prevSelectedKey => {
dispatch({
type: 'assetmanage.queryAllDirectoryAsTree',
callback: data => {
setLoading(false)
setLoadedKeys([])
setData(data)
if ((data??[]).length > 0) {
const newDataList = []
generateList(data, newDataList)
setDataList(newDataList)
if (resetSelectedNode) {
resetSelectedNodeLogic()
}
}
},
error: () => {
setLoading(false)
}
})
return prevSelectedKey
})
}
const getPermissions = () => {
dispatch({
type: 'assetmanage.getPrivilegeByRange',
payload: {
range: getAssetRange(AssetManageReference),
},
callback: data => {
setPermissions(data);
}
})
}
const onAddClick = () => {
setUpdateNodeParam({
visible: true,
action: 'add',
id: selectedKey
})
}
const onImportClick = () => {
setImportNodeParam({
visible: true,
reference: AssetManageReference,
dirId: selectedKey
})
}
const onCustomClick = () => {
setCustomNodeParam({
visible: true,
reference: AssetManageReference,
})
}
const onDeleteNodeClick = (node) => {
modal.confirm({
title: '提示',
content: '节点下可能包含资产信息,删除后将把资产从该目录上移除,确定继续吗?',
onOk: () => {
dispatch({
type: 'assetmanage.deleteDirectory',
payload: {data: [ rightSelectedNode?.nodeId ]},
callback: () => {
showMessage("success","删除成功")
if (rightSelectedNode?.nodeId === selectedKey) {
setSelectedKey()
getTreeData()
} else {
getTreeData(false)
}
}
})
}
})
}
const onMoveNodeClick = (steps) => {
setLoading(true);
dispatch({
type: 'assetmanage.upDownDirectory',
payload: {
params: {
dirId: rightSelectedNode?.nodeId,
steps
}
},
callback: () => {
showMessage('success', (steps===1)?'上移目录成功':'下移目录成功');
getTreeData(false)
},
error: () => {
setLoading(false)
}
});
}
const onRefreshClick = () => {
getTreeData(false)
}
const onTreeExpand = (expandedKeys) => {
setExpandedKeys(expandedKeys)
setAutoExpandParent(false)
}
const onTreeSelect = (selectedKeys, { selectedNodes }) => {
if (selectedKeys.length === 0 || selectedNodes.length === 0) {
return
}
setSelectedKey(selectedKeys[0])
onClick && onClick(selectedNodes[0])
}
const onUpdateNodeCancel = (refresh = false, nodeId = undefined) => {
setUpdateNodeParam(prevParam => {
if (refresh) {
if (prevParam.action !== 'add' && nodeId) {
setSelectedKey(nodeId)
getTreeData()
} else {
getTreeData(false)
}
}
return {
visible: false,
action: undefined,
id: undefined
}
})
}
const onImportNodeCancel = (refresh = false, resetSelectedNode = false) => {
setImportNodeParam({
visible: false,
reference: undefined,
dirId: undefined
})
refresh && getTreeData(resetSelectedNode)
}
const onCustomNodeCancel = (refresh = false) => {
setCustomNodeParam({
visible: false,
reference: undefined,
})
if (refresh) {
getTreeData(false)
}
}
const onMenuItemClick = (key, node) => {
console.log('key', key)
if (key === 'delete') {
onDeleteNodeClick(node)
} else if (key === 'edit') {
setUpdateNodeParam({
visible: true,
action: 'edit',
id: rightSelectedNode?.nodeId
})
} else if (key === 'up') {
onMoveNodeClick(1)
} else if (key === 'down') {
onMoveNodeClick(-1)
}
}
const onLoadData = ({ key, children }) =>
new Promise((resolve) => {
if (children) {
resolve()
return
}
setLoadedKeys([...loadedKeys, key])
dispatch({
type: 'assetmanage.getDirectoryChild',
payload: {
parentId: key,
},
callback: (_data) => {
let newData = updateTreeData(data, key, _data??[])
setData(newData)
resolve()
},
error: () => {
resolve()
}
})
})
const onAutoCompleteSearch = (searchText) => {
setKeyword(searchText)
setOptions(!searchText?[]:(dataList||[]).filter(item => item.value.indexOf(searchText)!==-1))
}
const onAutoCompleteSelect = (value, option) => {
const paths = value.split('/')
setKeyword(paths[paths.length-1])
setSelectedKey(option.key)
resetSelectedNodeLogic()
}
const exportMenu = (
<Menu>
<Menu.Item>
<div style={{ textAlign: 'center' }} onClick={() => {
window.open(`/api/dataassetmanager/directoryApi/export?dataAsset=${getAssetType(AssetManageReference)}`)
}}>
导出所有
</div>
</Menu.Item>
<Menu.Item>
<div style={{ textAlign: 'center' }} onClick={() => {
if(selectedKey){
dispatch({
type: 'assetmanage.getDirectoryById',
payload: {
dirId: selectedKey,
dataAsset: getAssetType(AssetManageReference)
},
callback: data => {
window.open(`/api/dataassetmanager/directoryApi/export?parentPath=${data.path}`);
}
})
} else {
showMessage("warn","请选择目录")
}
}}>
导出选中目录
</div>
</Menu.Item>
</Menu>
)
return (
<div className='resource-manage-tree'>
<div className='header p-3'>
<PermissionButton
defaultPermission={havePermission}
tip="新增目录"
type="text"
icon={<PlusOutlined />}
onClick={onAddClick}
/>
<Tooltip title="刷新目录">
<Button type="text" icon={<ReloadOutlined />} onClick={onRefreshClick} />
</Tooltip>
<PermissionButton
defaultPermission={havePermission}
tip="导入目录"
type="text"
icon={<ImportOutlined />}
onClick={onImportClick}
/>
<Dropdown overlay={havePermission?exportMenu:<></>} placement="bottomCenter" >
<PermissionButton
defaultPermission={havePermission}
tip="导出目录"
type="text"
icon={<ExportOutlined />}
/>
</Dropdown>
<PermissionButton
defaultPermission={havePermission}
tip="自定义目录"
type="text"
icon={<SettingOutlined />}
onClick={onCustomClick}
/>
</div>
<div className='p-3'>
<Spin spinning={loading}>
<AutoComplete
allowClear
value={keyword}
style={{ marginBottom: 10, width: '100%' }}
onSelect={onAutoCompleteSelect}
onSearch={onAutoCompleteSearch}
onClear={() => {
setKeyword()
}}
>
{
(options||[]).map((item, index) => {
return (
<AutoComplete.Option key={item.key} value={item.value}>
<div style={{ whiteSpace: 'normal' }}>
{highlightSearchContentByTerms(item.value, [keyword])}
</div>
</AutoComplete.Option>
);
})
}
</AutoComplete>
<Tree
className='tree'
showLine
showIcon={false}
autoExpandParent={autoExpandParent}
treeData={treeData}
loadData={onLoadData}
loadedKeys={loadedKeys}
onExpand={onTreeExpand}
onSelect={onTreeSelect}
expandedKeys={expandedKeys}
selectedKeys={[selectedKey]}
shouldRowContextMenu={(node) => {
setRightSelectedNode(node)
return havePermission
}}
menuData={menuData}
onMenuItemClick={onMenuItemClick}
/>
</Spin>
</div>
<UpdateNode
{...updateNodeParam}
onCancel={onUpdateNodeCancel}
/>
<ImportNode
{...importNodeParam}
onCancel={onImportNodeCancel}
/>
<CustomNode
action='add'
{...customNodeParam}
onCancel={onCustomNodeCancel}
/>
{contextHolder}
</div>
)
}
export default FC
\ No newline at end of file
...@@ -21,7 +21,7 @@ const FC = (props) => { ...@@ -21,7 +21,7 @@ const FC = (props) => {
const checkedKeys = basicRef.current?.getCheckedKeys() const checkedKeys = basicRef.current?.getCheckedKeys()
if ((checkedKeys??[]).length === 0) { if ((checkedKeys??[]).length === 0) {
showMessage('warn', '请先选择资目录') showMessage('warn', '请先选择资目录')
return return
} }
...@@ -139,7 +139,7 @@ export const Basic = React.forwardRef(function ({ items, onCheck }, ref) { ...@@ -139,7 +139,7 @@ export const Basic = React.forwardRef(function ({ items, onCheck }, ref) {
type: 'assetmanage.queryResourceDirectoryAsTree', type: 'assetmanage.queryResourceDirectoryAsTree',
callback: data => { callback: data => {
setLoading(false) setLoading(false)
const newData = (data??[]).filter(item => item.resourceType !== 'resource') const newData = (data??[]).filter(item => item.resourceType !== 'custom')
setData(newData) setData(newData)
if ((newData??[]).length > 0) { if ((newData??[]).length > 0) {
const newDataList = [] const newDataList = []
......
...@@ -1674,7 +1674,7 @@ export const MetadataColumnTooltipTitle = ({ data }) => { ...@@ -1674,7 +1674,7 @@ export const MetadataColumnTooltipTitle = ({ data }) => {
) )
} }
const MetadataColumn = ({ data }) => { export const MetadataColumn = ({ data }) => {
const decodeData = React.useMemo(() => { const decodeData = React.useMemo(() => {
if (data) { if (data) {
try { try {
......
...@@ -4,7 +4,7 @@ import { PlusOutlined, ReloadOutlined, ImportOutlined, ExportOutlined, SettingOu ...@@ -4,7 +4,7 @@ import { PlusOutlined, ReloadOutlined, ImportOutlined, ExportOutlined, SettingOu
import produce from 'immer' import produce from 'immer'
import { dispatch } from '../../../model' import { dispatch } from '../../../model'
import { showMessage, highlightSearchContentByTerms, showNotifaction, getAssetType } from '../../../util' import { showMessage, highlightSearchContentByTerms, showNotifaction, getAssetType, getAssetRange } from '../../../util'
import Tree from '../../../util/Component/Tree' import Tree from '../../../util/Component/Tree'
import PermissionButton from '../../../util/Component/PermissionButton' import PermissionButton from '../../../util/Component/PermissionButton'
import UpdateNode from './update-node' import UpdateNode from './update-node'
...@@ -27,7 +27,7 @@ export const generateList = (data, list, path = null, subjectNodeId = null) => { ...@@ -27,7 +27,7 @@ export const generateList = (data, list, path = null, subjectNodeId = null) => {
} }
} }
const updateTreeData = (list, key, children) => { export const updateTreeData = (list, key, children) => {
return list.map((node) => { return list.map((node) => {
if (node.nodeId === key) { if (node.nodeId === key) {
return {...node, children} return {...node, children}
...@@ -111,7 +111,7 @@ const FC = (props) => { ...@@ -111,7 +111,7 @@ const FC = (props) => {
<span className={(g.level===1)?'title-color':'text-color'}> <span className={(g.level===1)?'title-color':'text-color'}>
{g.text} {g.text}
{ {
//自定义类型栏目不统计资 //自定义类型栏目不统计资
(g.level === 1 && g.resourceType === 'custom') ? null : <span>{` (${g.dataAssetAndSubDirCount})`}</span> (g.level === 1 && g.resourceType === 'custom') ? null : <span>{` (${g.dataAssetAndSubDirCount})`}</span>
} }
</span> </span>
...@@ -231,7 +231,7 @@ const FC = (props) => { ...@@ -231,7 +231,7 @@ const FC = (props) => {
dispatch({ dispatch({
type: 'assetmanage.getPrivilegeByRange', type: 'assetmanage.getPrivilegeByRange',
payload: { payload: {
range: 'dataAsset_dataAssetManage', range: getAssetRange(ResourceManageReference),
}, },
callback: data => { callback: data => {
setPermissions(data); setPermissions(data);
......
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