Commit 9ea2318b by zhaochengxiang

未挂载资产

parent 075236c5
......@@ -234,25 +234,18 @@ const AssetAction = (props) => {
}
const jumpToRelation = (relation) => {
if (!readOnly) {
let event = new Event('storage');
event.key = 'assetRelationOnClickEvent';
event.relation = relation;
window?.dispatchEvent(event);
} else {
const timestamp = new Date().getTime();
const timestamp = new Date().getTime();
if (relation.resourceType==='innerSource'||relation.resourceType==='outerSource') {
if (checkMenuAdmit('asset-resource-browse')) {
window.open(`/center-home/menu/asset-resource-browse?${AnchorId}=${relation?.dataAssetId}&${AnchorDirId}=${relation?.dirId}&timestamp=${timestamp}`);
}
} else if (relation.resourceType==='dataAsset') {
if (checkMenuAdmit('asset-browse')) {
window.open(`/center-home/menu/asset-browse?${AnchorId}=${relation?.dataAssetId}&${AnchorDirId}=${relation?.dirId}&timestamp=${timestamp}`);
}
} else {
showMessage('warn', '资产类型不是资源也不是资产!');
if (relation.resourceType==='innerSource'||relation.resourceType==='outerSource') {
if (checkMenuAdmit('asset-resource-browse')) {
window.open(`/center-home/menu/asset-resource-browse?${AnchorId}=${relation?.dataAssetId}&${AnchorDirId}=${relation?.dirId}&timestamp=${timestamp}`);
}
} else if (relation.resourceType==='dataAsset') {
if (checkMenuAdmit('asset-browse')) {
window.open(`/center-home/menu/asset-browse?${AnchorId}=${relation?.dataAssetId}&${AnchorDirId}=${relation?.dirId}&timestamp=${timestamp}`);
}
} else {
showMessage('warn', '资产类型不是资源也不是资产!');
}
}
......
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??[]).toString(),
},
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()
}, [])
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 getTreeData = () => {
setLoading(true)
dispatch({
type: 'assetmanage.queryDataAssetManageTree',
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 from 'react';
import AssetTable from '../AssetManage/Component/AssetTable';
import AssetTable from './table';
import { AssetRecycleReference } from '../../../util/constant';
const AssetRecycle = (props) => {
......
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 { AssetBrowseReference, AssetRecycleReference } from '../../../util/constant'
import PermissionButton from '../../../util/Component/PermissionButton'
import PermissionMenuItem from '../../../util/Component/PermissionMenuItem'
import ChangeCatalog from './change-catalog'
import FilterElement from '../AssetManage/Component/FilterElementModal'
import TagCell from '../Model/Component/tag-help'
import { MetadataColumn } from '../AssetResourceManage/table'
import AssetDetailDrawer from '../AssetManage/Component/AssetDetailDrawer'
import '../AssetManage/Component/AssetTable.less'
const FC = () => {
const [args, setArgs] = React.useState(() => ({
params: {
page: defaultPage.pageNum,
size: defaultPage.pageSize,
keyword: undefined,
},
}))
const [ permissions, setPermissions ] = React.useState()
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 [row, setRow] = React.useState()
const [selectedRows, setSelectedRows] = 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 [filterElementParams, setFilterElementParams] = React.useState({
visible: false,
type: undefined,
reference: undefined
})
const [changeCatalogParams, setChangeCatalogParams] = React.useState({
visible: false,
items: undefined
})
const [assetDetailParams, setAssetDetailParams] = React.useState({
visible: false,
id: undefined,
dirId: undefined,
reference: undefined,
})
const [page, setPage] = usePage()
const [modal, contextHolder] = Modal.useModal()
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
}, [])
React.useEffect(() => {
getPermissions()
getElements()
const $$keyword = $keyword.pipe(debounceTime(1000)).subscribe((keyword) => {
setArgsAndPage({ keyword })
})
return () => {
$$keyword.unsubscribe()
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
React.useEffect(() => {
getAssets()
}, [args])
React.useEffect(() => {
if (data) {
getResourceTag()
}
}, [data])
const notElementCol = [
{
title: '标签',
dataIndex: 'tag',
width: 360,
className: 'table-tag-cell',
render: (_, record) => <div onClick={(e) => {e?.stopPropagation()}}>
<TagCell
id={record.id}
did={record.dirId}
type='dataAsset'
tags={resoureTagMap?.[`${record.id}`]}
/>
</div>
}
]
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 'calc(100vh - 199px - 72px)'
}, [])
const getPermissions = () => {
dispatch({
type: 'assetmanage.getPrivilegeByRange',
payload: {
range: getAssetRange(AssetRecycleReference),
},
callback: data => {
setPermissions(data)
}
})
}
const getElements = () => {
setLoadingElements(true)
dispatch({
type: 'assetmanage.listFilterElements',
payload: {
range: getAssetRange(AssetRecycleReference),
dataAssetType: getAssetType(AssetRecycleReference)
},
callback: data => {
setLoadingElements(false)
setElements(data)
},
error: () => {
setLoadingElements(false)
}
})
}
const getAssets = () => {
setLoading(true)
dispatch({
type: 'assetmanage.listRecycleBinDataAssetsByPage',
payload: {
pageNum: args.params.page,
pageSize: args.params.size,
keyword: args.params.keyword,
},
callback: data => {
setLoading(false)
setData(data?.data)
setTotal(data?.total)
},
error: () => {
setLoading(false)
}
})
}
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 onExportClick = () => {
window.open(`/api/dataassetmanager/dataAssetApi/exportByDataAssetIds?dataAssetIds=${(selectedRows??[]).map(item => item.id).toString()}`);
}
const onMountClick = () => {
setChangeCatalogParams({
visible: true,
items: selectedRows
})
}
const onFilterElementClick = () => {
setFilterElementParams({
visible: true,
type: 'user',
reference: AssetBrowseReference
})
}
const onRecoveryClick = () => {
modal.confirm({
title: '提示',
content: '您确定要恢复这些资产吗?',
onOk: () => {
dispatch({
type: 'assetmanage.recoveryFromRecycleBin',
payload: {
data: (selectedRows??[]).map(item => item.id)
},
callback: (data) => {
if (data?.message) {
showNotifaction('提示', data?.message, 5);
}
getAssets()
setSelectedRows()
}
})
}
})
}
const onDeleteClick = () => {
modal.confirm({
title: '提示',
content: '您确定要永久删除这些资产吗?',
onOk: () => {
dispatch({
type: 'assetmanage.deleteDataAssets',
payload: {
data: (selectedRows??[]).map(item => item.id)
},
callback: () => {
showMessage("success","删除成功")
getAssets()
setSelectedRows()
},
error: () => {
}
})
}
})
}
const refreshPage = () => {
getElements()
getAssets()
}
return (
<div className='asset-list'>
<div
className='flex'
style={{
padding: '15px',
alignItems: 'center',
justifyContent: 'space-between',
}}
>
<Space>
<PermissionButton
permissionKey='export'
permissions={permissions}
disabled={(selectedRows??[]).length===0}
tip={(selectedRows??[]).length===0?'请先选择资产':''}
onClick={onExportClick}
>
导出
</PermissionButton>
<PermissionButton
permissionKey='loadDataAsset'
permissions={permissions}
disabled={(selectedRows??[]).length===0}
tip={(selectedRows??[]).length===0?'请先选择资产':''}
onClick={onMountClick}
>
挂载
</PermissionButton>
<PermissionButton
permissionKey='resumeDataAsset'
permissions={permissions}
disabled={(selectedRows??[]).length===0}
tip={(selectedRows??[]).length===0?'请先选择资产':''}
onClick={onRecoveryClick}
>
恢复
</PermissionButton>
<PermissionButton
permissionKey='delete'
permissions={permissions}
disabled={(selectedRows??[]).length===0}
tip={(selectedRows??[]).length===0?'请先选择资产':''}
onClick={onDeleteClick}
>
删除
</PermissionButton>
<Button onClick={onFilterElementClick}>可见列设置</Button>
</Space>
<Input size="middle"
placeholder="资产要素值"
value={keyword}
bordered={true} allowClear
onChange={(e) => {
const keyword = e.target.value
setKeyword(keyword)
$keyword.next((keyword??'').trim())
}}
style={{ width: 270 }}
/>
</div>
<div className='px-3'>
<Table
maxHeight={tableMaxHeight}
loading={loading||loadingElements}
columns={columns}
dataSource={tableData}
pageSize={page.pageSize} pageNum={page.pageNum} total={total??0}
onRowClick={(event, value) => {
setRow(value)
setAssetDetailParams({
visible: true,
id: value?.id,
dirId: value?.dirId,
reference: AssetBrowseReference
})
}}
rowClassName={(record, index) => (record?.id === row?.id) ? 'yy-table-select-row' : ''}
onPaginate={(page, pageSize) => {
setRow()
setPageAndArgs({ pageNum: page, pageSize })
}}
rowSelection={{
selectedRowKeys: (selectedRows??[]).map(item => item.id),
onChange: (selectedRowKeys, selectedRows) => {
setSelectedRows(selectedRows)
},
}}
/>
</div>
<FilterElement
{...filterElementParams}
onCancel={(refresh = false) => {
setFilterElementParams({
visible: false,
type: undefined,
reference: undefined
})
if (refresh) {
refreshPage()
}
}}
/>
<ChangeCatalog
{...changeCatalogParams}
onCancel={(refresh) => {
setChangeCatalogParams({
visible: false,
items: undefined
})
if (refresh) {
refreshPage()
}
}}
/>
<AssetDetailDrawer
{...assetDetailParams}
onCancel={() => {
setAssetDetailParams({
visible: false,
id: undefined,
dirId: undefined,
reference: undefined
})
}}
/>
{contextHolder}
</div>
)
}
export default FC
\ No newline at end of file
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