Commit f0cae88d by zhaochengxiang

调整资产管理代码

parent 578db1a1
...@@ -68,7 +68,6 @@ export function listAllTopics(payload) { ...@@ -68,7 +68,6 @@ export function listAllTopics(payload) {
return GetJSON("/dataassetmanager/directoryApi/listAllTopics", payload); return GetJSON("/dataassetmanager/directoryApi/listAllTopics", payload);
} }
export function directoryImport(payload) { export function directoryImport(payload) {
return filePost2("/dataassetmanager/directoryApi/import", payload); return filePost2("/dataassetmanager/directoryApi/import", payload);
} }
......
...@@ -15,7 +15,7 @@ import "./AssetTable.less"; ...@@ -15,7 +15,7 @@ import "./AssetTable.less";
const AssetTable = (props) =>{ const AssetTable = (props) =>{
const { nodeId, node } = props const { nodeId } = props
const [ loading, setLoading ] = useState(false); const [ loading, setLoading ] = useState(false);
const [ assetNames, setAssetNames ] = useState([]); const [ assetNames, setAssetNames ] = useState([]);
const [ assets, setAssets ] = useState([]); const [ assets, setAssets ] = useState([]);
...@@ -127,7 +127,7 @@ const AssetTable = (props) =>{ ...@@ -127,7 +127,7 @@ const AssetTable = (props) =>{
} }
const exportAsset = () => { const exportAsset = () => {
window.open(`/api/dataassetmanager/dataAssetApi/export?parentPath=${node.path||''}`); // window.open(`/api/dataassetmanager/dataAssetApi/export?parentPath=${node.path||''}`);
} }
const detailAsset = (item)=>{ const detailAsset = (item)=>{
...@@ -266,7 +266,7 @@ const AssetTable = (props) =>{ ...@@ -266,7 +266,7 @@ const AssetTable = (props) =>{
<Button type="primary" danger onClick={ deleteAssets } >删除</Button> <Button type="primary" danger onClick={ deleteAssets } >删除</Button>
<Popover <Popover
placement="bottomRight" placement="bottomRight"
content={ <ImportAsset node={node} onCancel={onImportAssetVisibleChange} /> } content={ <ImportAsset nodeId={nodeId} onCancel={onImportAssetVisibleChange} /> }
title='资产导入' title='资产导入'
visible={importAssetVisible} visible={importAssetVisible}
onVisibleChange={onImportAssetVisibleChange} onVisibleChange={onImportAssetVisibleChange}
......
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import {Card, Spin, Button, Tooltip, Tree, Input, Dropdown, Menu, Space} from 'antd'; import {Card, Spin, Button, Tooltip, Tree, Input, Dropdown, Menu, Space, Modal} from 'antd';
import { PlusOutlined, ImportOutlined,EditOutlined,DeleteOutlined,ExportOutlined,SyncOutlined } from '@ant-design/icons'; import { PlusOutlined, ImportOutlined,EditOutlined,DeleteOutlined,ExportOutlined,SyncOutlined } from '@ant-design/icons';
import { dispatch } from '../../../../model'; import { dispatch } from '../../../../model';
import ImportDirectory from './ImportDirectory'; import ImportDirectory from './ImportDirectory';
import UpdateDirectoryModal from './UpdateDirectoryModal';
import { showMessage } from '../../../../util';
import './AssetTree.less'; import './AssetTree.less';
const AssetTree = (props) => { const AssetTree = (props) => {
...@@ -17,6 +19,9 @@ const AssetTree = (props) => { ...@@ -17,6 +19,9 @@ const AssetTree = (props) => {
const [ autoExpandParent, setAutoExpandParent ] = useState(false); const [ autoExpandParent, setAutoExpandParent ] = useState(false);
const [ currentDirId, setCurrentDirId ] = useState(''); const [ currentDirId, setCurrentDirId ] = useState('');
const [ importDirectoryVisible, setImportDirectoryVisible ] = useState(false); const [ importDirectoryVisible, setImportDirectoryVisible ] = useState(false);
const [ updateDirectoryModalVisible, setUpdateDirectoryModalVisible ] = useState(false);
const [ updateDirectoryAction, setUpdateDirectoryAction ] = useState('');
const [modal, contextHolder] = Modal.useModal();
useEffect(() => { useEffect(() => {
getAllDirectoryAsTree(); getAllDirectoryAsTree();
...@@ -75,11 +80,13 @@ const AssetTree = (props) => { ...@@ -75,11 +80,13 @@ const AssetTree = (props) => {
}; };
const addDir = () => { const addDir = () => {
setUpdateDirectoryAction('add');
setUpdateDirectoryModalVisible(true);
} }
const updateDir = () => { const editDir = () => {
setUpdateDirectoryAction('edit');
setUpdateDirectoryModalVisible(true);
} }
const refreshTree = () => { const refreshTree = () => {
...@@ -91,15 +98,45 @@ const AssetTree = (props) => { ...@@ -91,15 +98,45 @@ const AssetTree = (props) => {
} }
const exportAllDir = () => { const exportAllDir = () => {
window.open('/api/dataassetmanager/directoryApi/export');
} }
const exportCurrentDir = () => { 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 = () => { const deleteDir = () => {
if (currentDirId) {
modal.confirm({
title: '提示',
content: '节点下可能包含资产信息,删除后将把资产从该目录上移除,确定继续吗?',
onOk: () => {
dispatch({
type: 'assetmanage.deleteDirectory',
payload: {data: [ currentDirId ]},
callback: () => {
showMessage("success","删除成功");
getAllDirectoryAsTree(true);
}
})
}
})
} else {
showMessage('info', '请先选择目录');
}
} }
const onChange = (e) => { const onChange = (e) => {
...@@ -135,6 +172,11 @@ const AssetTree = (props) => { ...@@ -135,6 +172,11 @@ const AssetTree = (props) => {
setAutoExpandParent(false); setAutoExpandParent(false);
}; };
const onUpdateDirectoryCancel = (refresh=false) => {
setUpdateDirectoryModalVisible(false);
refresh && getAllDirectoryAsTree(false);
}
const onImportDirectoryCancel = (refresh=false, resetCurrentDirId=false) => { const onImportDirectoryCancel = (refresh=false, resetCurrentDirId=false) => {
setImportDirectoryVisible(false); setImportDirectoryVisible(false);
refresh && getAllDirectoryAsTree(resetCurrentDirId); refresh && getAllDirectoryAsTree(resetCurrentDirId);
...@@ -189,7 +231,7 @@ const AssetTree = (props) => { ...@@ -189,7 +231,7 @@ const AssetTree = (props) => {
<Button shape="circle" icon={<PlusOutlined />} onClick={addDir} /> <Button shape="circle" icon={<PlusOutlined />} onClick={addDir} />
</Tooltip> </Tooltip>
<Tooltip title="修改"> <Tooltip title="修改">
<Button shape="circle" icon={<EditOutlined />} onClick={updateDir} /> <Button shape="circle" icon={<EditOutlined />} onClick={editDir} />
</Tooltip> </Tooltip>
<Tooltip title="刷新"> <Tooltip title="刷新">
<Button shape="circle" icon={<SyncOutlined />} onClick={refreshTree} /> <Button shape="circle" icon={<SyncOutlined />} onClick={refreshTree} />
...@@ -230,12 +272,18 @@ const AssetTree = (props) => { ...@@ -230,12 +272,18 @@ const AssetTree = (props) => {
/> />
</Spin> </Spin>
<UpdateDirectoryModal
visible={ updateDirectoryModalVisible }
onCancel={ onUpdateDirectoryCancel }
action={ updateDirectoryAction }
dirId={ currentDirId }
/>
<ImportDirectory <ImportDirectory
visible={ importDirectoryVisible } visible={ importDirectoryVisible }
onCancel={ onImportDirectoryCancel } onCancel={ onImportDirectoryCancel }
dirId={ currentDirId } dirId={ currentDirId }
/> />
{contextHolder}
</Card> </Card>
) )
} }
......
...@@ -24,7 +24,7 @@ class ImportAsset extends React.Component { ...@@ -24,7 +24,7 @@ class ImportAsset extends React.Component {
} }
onOk = () => { onOk = () => {
const { node, onCancel } = this.props; const { nodeId, onCancel } = this.props;
const { fileList } = this.state; const { fileList } = this.state;
if ((fileList||[]).length === 0) { if ((fileList||[]).length === 0) {
...@@ -34,8 +34,14 @@ class ImportAsset extends React.Component { ...@@ -34,8 +34,14 @@ class ImportAsset extends React.Component {
this.setState({ confirmLoading: true }, () => { this.setState({ confirmLoading: true }, () => {
dispatch({ dispatch({
type: 'assetmanage.getDirectoryById',
payload: {
dirId: nodeId
},
callback: data => {
dispatch({
type: 'assetmanage.assetImport', type: 'assetmanage.assetImport',
payload: { fileList: fileList[0], params: { parentPath: node.path||'' } }, payload: { fileList: fileList[0], params: { parentPath: data.path||'' } },
callback: () => { callback: () => {
this.setState({ confirmLoading: false }, () => { this.setState({ confirmLoading: false }, () => {
onCancel && onCancel(false, true); onCancel && onCancel(false, true);
...@@ -45,6 +51,8 @@ class ImportAsset extends React.Component { ...@@ -45,6 +51,8 @@ class ImportAsset extends React.Component {
this.setState({ confirmLoading: false }); this.setState({ confirmLoading: false });
} }
}); });
}
})
}); });
} }
......
.asset-tree {
.yy-card-head-title {
padding: 0;
}
.yy-tree-list {
height: calc(100vh - 64px - 30px - 53px - 20px - 42px) !important;
overflow: auto !important;
}
}
\ No newline at end of file
import React,{useState, useEffect} from "react"
import {Modal,Form,Upload,Button,Radio} from "antd"
import { PlusOutlined } from '@ant-design/icons';
import { dispatch } from '../../../../model';
import { showMessage,showNotifaction} from '../../../../util';
const ThemeFile = (props)=>{
const {fileVisible,handleCancle,editBox,selectKey,setTreeRebuild} = props
const [upLoad,setUpLoad] = useState(false)
const [form] = Form.useForm()
useEffect(()=>{
if(fileVisible){
form.resetFields()
}
//eslint-disable-next-line react-hooks/exhaustive-deps
},[fileVisible])
const normFile = (e) => {
let data = []
if(e.fileList[0]){
data = e.fileList.slice(-1)
}
return data;
};
const prop = {
beforeUpload: (file) => {
const isLt20M = file.size / 1024 / 1024 < 2000;
if (!isLt20M) {
return showMessage("warn","上传文件不能超过 20MB!")
}
if ( file.type !== "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ) {
return showMessage("warn","上传格式错误")
}
return false;
},
};
const upload = ()=>{
form.validateFields().then((value)=>{
setUpLoad(true)
if(selectKey){
if(value.type===1){
dispatch({
type: 'assetmanage.directoryImport',
payload: { fileList: value.file[0].originFileObj },
callback: data => {
setTreeRebuild({build:new Date().getTime(),type:'build'})
setUpLoad(false)
if(data){
let msg=data.replace(RegExp(";", "g"),"<br />")
showNotifaction('导入提示', msg);
}
handleCancle()
},
error: (error) => {
console.log(error)
setUpLoad(false)
}
})
}else{
dispatch({
type: 'assetmanage.directoryImport',
payload: { params:{parentPath: editBox.path},fileList: value.file[0].originFileObj },
callback: data => {
setUpLoad(false)
if(data){
let msg=data.replace(RegExp(";", "g"),"<br />")
showNotifaction('导入提示', msg);
}
setTreeRebuild({build:new Date().getTime(),type:'build'})
handleCancle()
},
error: () => {
}
})
}
}else{
dispatch({
type: 'assetmanage.directoryImport',
payload: {fileList: value.file[0].originFileObj },
callback: data => {
setUpLoad(false)
handleCancle()
showMessage("success","导入成功")
setTreeRebuild({build:new Date().getTime(),type:'build'})
},
error: () => {
}
})
}
}).catch(()=>{
setUpLoad(false)
})
}
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 17 },
},
};
const download=()=>{
window.open("/data-govern/docs/AssetThemeModel.xlsx");
}
return(
<Modal
title={`目录导入`}
visible={fileVisible}
// width={800}
onCancel={()=>{handleCancle()}}
maskClosable={false}
footer={[
<div key="btn1" >
<Button type="primary" onClick={()=>download()} >模版下载</Button>
<Button type="primary" onClick={upload} loading={upLoad}>上传</Button>
<Button onClick={handleCancle}>返回</Button>
</div>
]}
>
<Form {...formItemLayout} form={form}>
<Form.Item
label="挂载位置"
name="type"
rules={[{ required: true, message: '必填项'}]}
>
<Radio.Group >
<Radio value={1} >父节点导入</Radio>
<Radio value={2} disabled={selectKey!==undefined?false:true}>选中节点导入</Radio>
</Radio.Group>
</Form.Item>
<Form.Item
label="文件"
name="file"
rules={[{ required: true, message: '请上传附件'}]}
valuePropName='fileList'
getValueFromEvent= {normFile}
>
<Upload {...prop}>
<Button type='link' icon={<PlusOutlined/>} style={{padding:5}} > 上传</Button>
</Upload>
</Form.Item>
</Form>
</Modal>
)
}
export default ThemeFile;
\ No newline at end of file
import React,{useState, useEffect,} from "react"
import {Modal,Form,Input,Space,InputNumber,Button,Radio} from "antd"
import { dispatchLatest } from '../../../../model';
import { showMessage } from '../../../../util';
const TreeModal = (props)=>{
const {handleCancle,visible,editBox,addType,selectKey,getNodeDetail,setTreeRebuild,treeRebuild} = props
const [form] = Form.useForm()
const [saveLoad,setSaveLod] = useState(false)
useEffect(()=>{
if(visible){
reset()
}
//eslint-disable-next-line react-hooks/exhaustive-deps
},[visible])
const handleOk =async()=>{
setSaveLod(true)
form.validateFields().then((value)=>{
if(addType){
if(Number(value.type)===1){
let box = {
"code": value.code,
"name": value.name,
"order": value.order,
"remarks": value.order,
}
dispatchLatest({
type: 'assetmanage.addOrUpdateDirectory',
payload: {data:box},
callback: data => {
console.log(data)
showMessage("success","新增成功")
setTreeRebuild({...treeRebuild,build:new Date().getTime()})
handleCancle()
setSaveLod(false)
},
error: () => {
setSaveLod(false)
}
})
}else{
let box = {
"code": value.code,
"name": value.name,
"order": value.order,
"remarks": value.order,
}
dispatchLatest({
type: 'assetmanage.addOrUpdateDirectory',
payload: {params:{parentPath:editBox.path},data:box},
callback: data => {
console.log(data)
showMessage("success","新增成功")
setTreeRebuild({...treeRebuild,build:new Date().getTime()})
handleCancle()
setSaveLod(false)
},
error: () => {
setSaveLod(false)
}
})
}
}else{
let box = {
"code": value.code,
"name": value.name,
"order": value.order,
"remarks": value.remarks,
"id":editBox.id,
}
let parentPath = editBox.path.substring(0,editBox.path.lastIndexOf("/"));;
dispatchLatest({
type: 'assetmanage.addOrUpdateDirectory',
payload: {params:{parentPath:parentPath},data:box},
callback: data => {
setSaveLod(false)
getNodeDetail(data.id)
showMessage("success","修改成功")
setTreeRebuild({...treeRebuild,build:new Date().getTime()})
handleCancle()
},
error: () => {
setSaveLod(false)
}
})
setSaveLod(false)
}
}).catch(()=>{
setSaveLod(false)
})
}
const reset = () =>{
if(addType){
form.resetFields()
}else{
let box = {
code:editBox.code,
name:editBox.name,
order:editBox.order||'',
remarks:editBox.remarks||'',
}
form.setFieldsValue(box)
}
}
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 17 },
},
};
return(
<Modal
forceRender
title={`资产目录信息`}
visible={visible}
width={600}
onCancel={()=>{handleCancle()}}
// style={{ top: 30}}
footer={
<Space>
<Button type="primary" onClick={handleOk} loading={saveLoad}>提交</Button>
<Button onClick={()=>reset()} >重置</Button>
<Button onClick={()=>handleCancle()}>返回</Button>
</Space>
}
>
<Form {...formItemLayout} form={form}>
{addType&&<Form.Item
label="类型"
name="type"
rules={[{ required: true, message: '必填项' }]}
>
<Radio.Group >
<Radio value={1} >主题</Radio>
<Radio value={2} disabled={selectKey!==undefined?false:true}>目录</Radio>
</Radio.Group>
</Form.Item>}
<Form.Item
label="编号"
name="code"
rules={[{ required: true, message: '必填项' }]}
>
<Input placeholder="请输入编号" />
</Form.Item>
<Form.Item
label="名称"
name="name"
rules={[{ required: true, message: '必填项' }]}
>
<Input placeholder="请输入名称" />
</Form.Item>
<Form.Item
label="权重"
name="order"
rules={[{ required: true, message: '必填项' }]}
>
<InputNumber min={1} max={999} style={{width:'100%'}} placeholder="请输入权重(1-999)" />
</Form.Item>
{
!addType && (
<Form.Item
label="路径"
name="path"
>
<span>{editBox.path||''}</span>
</Form.Item>
)
}
<Form.Item
label="描述"
name="remarks"
>
<Input.TextArea placeholder="请输入描述" autoSize={{ minRows: 4, maxRows: 4 }} />
</Form.Item>
</Form>
</Modal>
)
}
export default TreeModal;
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import { Modal, Form, Input, Space, InputNumber, Button, Radio } from 'antd';
import { dispatch } from '../../../../model';
import { showMessage } from '../../../../util';
const UpdateDirectoryModal = (props) => {
const { visible, onCancel, dirId, action } = props;
const [ form ] = Form.useForm();
const [ dir, setDir ] = useState(null);
const [ confirmLoading, setConfirmLoading ] = useState(false);
useEffect(() => {
if (visible) {
onReset();
setDir(null);
if ((dirId||'')!=='') {
getDirectory();
}
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ visible ])
const getDirectory = () => {
setDir(null);
dispatch({
type: 'assetmanage.getDirectoryById',
payload: {
dirId
},
callback: data => {
setDir(data);
onReset();
}
})
}
const onOk = async () => {
try {
const row = await form.validateFields();
setConfirmLoading(true);
let payload = {
data: {
code: row.code,
name: row.name,
order: row.order,
remarks: row.remarks,
}
};
if (action === 'add') {
if (row.type === 'directory') {
if (dir === null) {
showMessage('warn', '资产目录节点信息正在加载中...');
return;
}
payload = { ...payload, params: {
parentPath: dir.path||''
}};
}
} else {
if (dir === null) {
showMessage('warn', '资产目录节点信息正在加载中...');
return;
}
payload.data = { ...payload.data, id: dirId };
const parentPath = dir.path.substring(0, dir.path.lastIndexOf("/"));;
payload = { ...payload, params: {
parentPath
}};
}
dispatch({
type: 'assetmanage.addOrUpdateDirectory',
payload: payload,
callback: () => {
setConfirmLoading(false);
onCancel && onCancel(true);
},
error: () => {
setConfirmLoading(false);
}
})
} catch (errInfo) {
console.log('Validate Failed:', errInfo);
}
}
const onReset = () => {
if(action === 'add') {
form.resetFields()
} else {
if (dir === null) {
showMessage('warn', '资产目录节点信息正在加载中...');
return;
}
form.setFieldsValue({ code: dir.code, name: dir.name||'', order: dir.order||'', remarks: dir.remarks||'' })
}
}
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 17 },
},
};
return (
<Modal
forceRender
title={`资产目录信息`}
visible={visible}
width={600}
onCancel={() => { onCancel && onCancel() }}
footer={
<Space>
<Button type="primary" onClick={onOk} loading={confirmLoading}>提交</Button>
<Button onClick={onReset} >重置</Button>
<Button onClick={() => onCancel && onCancel() }>返回</Button>
</Space>
}
>
<Form {...formItemLayout} form={form}>
{
action==='add' && <Form.Item
label="类型"
name="type"
rules={[{ required: true, message: '必填项' }]}
>
<Radio.Group >
<Radio value='theme' >主题</Radio>
<Radio value='directory' disabled={ dirId===null }>目录</Radio>
</Radio.Group>
</Form.Item>
}
<Form.Item
label="编号"
name="code"
rules={[{ required: true, message: '必填项' }]}
>
<Input placeholder="请输入编号" />
</Form.Item>
<Form.Item
label="名称"
name="name"
rules={[{ required: true, message: '必填项' }]}
>
<Input placeholder="请输入名称" />
</Form.Item>
<Form.Item
label="权重"
name="order"
rules={[{ required: true, message: '必填项' }]}
>
<InputNumber min={1} max={999} style={{ width:'100%' }} placeholder="请输入权重(1-999)" />
</Form.Item>
{
action !== 'add' && (
<Form.Item
label="路径"
name="path"
>
<span>{ dir ? (dir.path||''):'' }</span>
</Form.Item>
)
}
<Form.Item
label="描述"
name="remarks"
>
<Input.TextArea placeholder="请输入描述" autoSize={{ minRows: 4, maxRows: 4 }} />
</Form.Item>
</Form>
</Modal>
);
}
export default UpdateDirectoryModal;
\ No newline at end of file
import React from 'react'; import React, { useState } from 'react';
import { Row, Col } from 'antd'; import { Row, Col } from 'antd';
import LeftTree from "./components/LeftTree"
import AssetTable from "./components/AssetTable" import AssetTable from "./components/AssetTable"
import AssetTree from './components/AssetTree'; import AssetTree from './components/AssetTree';
class Index extends React.Component { const AssetManage = (props) => {
constructor(props) {
super(props);
this.state = {
nodeId:null,
node: null,
};
}
componentDidMount() {
}
setNodeId=(data)=>{ const [ nodeId, setNodeId ] = useState('');
this.setState({nodeId:data})
}
setNode = (data) => { const onTreeSelect = (value) => {
this.setState({ node: data }); setNodeId(value||'');
} }
render() {
return ( return (
<Row gutter={15} style={{backgroundColor:'#ededed'}}> <Row gutter={15} style={{backgroundColor:'#ededed'}}>
<Col span={6}> <Col span={6}>
<AssetTree /> <AssetTree onSelect={onTreeSelect} />
{/* <LeftTree setNodeId={this.setNodeId} setNode={this.setNode} nodeId={this.state.nodeId}/> */}
</Col> </Col>
<Col span={18}> <Col span={18}>
<AssetTable nodeId={this.state.nodeId} node={this.state.node} /> <AssetTable nodeId={nodeId} />
</Col> </Col>
</Row> </Row>
) )
}
} }
export default Index; export default AssetManage;
\ No newline at end of file \ No newline at end of file
...@@ -2,10 +2,10 @@ import React, { useState } from "react"; ...@@ -2,10 +2,10 @@ import React, { useState } from "react";
import { Modal } from "antd"; import { Modal } from "antd";
import { dispatch } from '../../../../model'; import { dispatch } from '../../../../model';
import LeftTree from '../../AssetManage/components/LeftTree'; import AssetTree from '../../AssetManage/components/AssetTree';
import { showMessage } from '../../../../util'; import { showMessage } from '../../../../util';
const AssetMount = (props)=>{ const AssetMount = (props) => {
const { onCancel,visible, item } = props; const { onCancel,visible, item } = props;
const [ nodeId, setNodeId ] = useState(null); const [ nodeId, setNodeId ] = useState(null);
...@@ -46,9 +46,9 @@ const AssetMount = (props)=>{ ...@@ -46,9 +46,9 @@ const AssetMount = (props)=>{
onCancel={()=>{ onCancel && onCancel()}} onCancel={()=>{ onCancel && onCancel()}}
onOk={ onOk } onOk={ onOk }
> >
<LeftTree <AssetTree
readOnly={true} readOnly={true}
setNodeId={(data) => { setNodeId(data); }} onSelect={(value) => setNodeId(value) }
/> />
</Modal> </Modal>
) )
......
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